I have a function:
void *findPos(void *param)
{
int origPos=(int)param;
...
}
Which I am calling as a thread runner:
pthread_create( &threadIdArray[i], NULL, findPos, (void *)i );
Now, this way, I get the value of origPos as the typecasted void pointer param, ie. i. This feels like a dirty hack to get around the limitation of being allowed to pass only void pointers to a thread runner function.
Can this be done in a cleaner way?
Edit:
Please note that I run the pthread_create() function in a i for loop, hence passing a pointer to i may not be a safe choice.
Sure: just supply a pointer to the int, as was the intention of the API designer:
void *findPos(void *param)
{
int origPos=*(int *)param;
...
}
pthread_create( &threadIdArray[i], NULL, findPos, &i );
Casting between int andvoid * is unsafe because the conversion is not necessarily invertible.
You must also ensure that i is still valid when the thread starts executing (if i has automatic storage duration, this would eg be the case if the calling function also calls pthread_join()).
In your case (i being a loop variable), you should duplicating the variable's value in a safe location, eg on the heap via malloc() or by pushing it on a stack with appropriate liefetime:
static int args[THREAD_COUNT];
for(int i = 0; i < THREAD_COUNT; ++i)
{
args[i] = i;
pthread_create(&threadIdArray[i], NULL, findPos, args + i);
}
You should be sure that on your system the value of your parameter has enough room inside a void-pointer (see data type intptr_t). Passing a double value could be problematic with your "direct" method.
I'm often using a parameter structur to pass values to thread (or other) functions.
struct Param {
double foo;
int bar;
};
Param param;
param.foo = 1.0;
param.bar = 1;
pthread_create( &threadIdArray[i], NULL, findPos, ¶m );
Well, you could pass a pointer to the value, or wrap the value in a struct and pass a pointer to that. The latter isn't cleaner per se, but more expandable if you ever need more than one int worth of parameters to your thread.
UPDATE:
I used to suggest use of use intptr_t from <stdint.h> to express that you intend to cast this integer to/from void *, but reading the documentation a bit more closely (thanks, Christoph) gives:
The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to a pointer to void, and the result will compare equal to the original pointer: intptr_t
This would seem to indicate, just as Christoph said, that you're not safe if you go this route, so don't
This is a hack that you shouldn't do if you want to have portable code. First the conversion back from void* is not necessarily well defined, as somebody else stated already.
But regardless of that, this is a dirty hack that goes against all possible intentions of the pthread_create API. Simply use something like this:
size_t * threadId = calloc(n, sizeof(size_t));
for (size_t i = 0; i < n; ++i) {
threadId[i] = i;
ptread_create(...., &threadId[i]);
}
And you don't have the congestion on i that you would have if you pass the same argument to all the threads.
I don't believe it's a dirty hack really. Wikipedia in its pthreads example does the same.
Related
I am having a hard time understanding why pthread_join's retval argument is a void**. I have read the manpage and tried to wrap my head around it but I still cannot fully understand it. I couldn't convince myself that retval cannot be a void*. Could someone please enlighten me?
Thank you very much in advance!
It's because you are supposed to supply the address of a void* to pthread_join.
pthread_join will then write the address supplied by pthread_exit(void*) into the variable (who's address you supplied).
Example scenario:
typedef struct {
// members
} input_data;
typedef struct {
// members
} output_data;
Starting thread side:
input_data id;
pthread_create(..., start_routine, &id);
void* start_routine(void *ptr) {
input_data *id = ptr;
output_data *od = malloc(sizeof *od);
// use the input data `id`, populate the output data `od`.
pthread_exit(od);
}
Joining side:
output_data *od;
pthread_join((void**) &od);
// use `od`
free(od);
Simple enough. The return value of thread func supplied to pthread_create is void*; pthread_join is supposed to return this value to caller.
It can not return this as a function return type (because it is already returning int to indicate the overall status of the call). The only other way as through out parameter.
And the way C does out paramters is by using a pointer to the actual type of the parameter - i.e. if you want to do int as an out parameter, the type of the argument would be int*. If your out parameter is void* (because this is what you are returning from pthread func!), the type of the argument becomes void**.
As an exercise, you can try to write a similar code yourself - first, create a function which returns void* (say, void* foo()), and than try to write another function which would call foo() and communicate result back to the caller.
The exiting thread is going to provide a pointer to some data. The pthread routines do not know what type that data has, so they receive the pointer as a void *.
The caller of pthread_join is going to receive that void *. Since the function return value is used for something else, the void * has to be received through a parameter. So the caller has to pass a pointer to where pthread_join will put the void *. That pointer is a pointer to a void *, which is a void **.
From the manpage:
If retval is not NULL, then pthread_join() copies the exit status of the target thread (i.e., the value that the target thread supplied to pthread_exit(3)) into the location pointed to by retval.
Let's look at the signature of pthread_exit.
noreturn void pthread_exit(void *retval);
So that means if we wanted to return an int from our thread it would look something like this:
void* foo() {
// ...
int value = 255;
pthread_exit(&value);
}
This works because the compiler doesn't care that it's an int* or a void*, either way it's a pointer of the same size.
Now we want to actually extract the return value of the thread using pthread_join.
void bar() {
pthread_t thread_id;
int *returnValue;
// create thread etc...
// the original type of returnValue was an `int*` so when we pass it in
// with "&" it's now become `int**`
pthread_join(thread_id, &returnValue);
printf("%d\n", *returnValue); // should print 255
}
In plain English pthread_join takes a pointer and sets it address to point at the retval from your thread. It's a void** because we need the address of the pointer to be able to set the underlying pointer to what we want.
I was trying to print a thread's return value and discovered that I'm still quite confused by the notion of double void-pointers.
My understanding was that a void* is a pointer to any datatype that can be dereferenced with an appropriate cast, but otherwise the "levels" of referencing are preserved like with regular typed pointers (i.e. you can't expect to get the same value that you put into **(int **)depth2 by dereferencing it only once like *depth2. ).
In the code (below) that I have scraped together for my thread-return-print, however, it seems that I'm not dereferencing a void pointer at all when I'm just casting it to (int). Is this a case of an address being used as value? If so, is this the normal way of returning from threads? Otherwise, what am I missing??
(I am aware that the safer way to manipulate data inside the thread might be caller-level storage, but I'm quite interested in this case and what it is that I don't understand about the void pointer.)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *myThread(void *arg)
{
return (void *)42;
}
int main()
{
pthread_t tid;
void *res; // res is itself a void *
pthread_create(&tid, NULL, myThread, NULL);
pthread_join(tid, &res); // i pass its address, so void** now
printf(" %d \n", (int)res); // how come am i able to just use it as plain int?
return 0;
}
First of all, the purpose of pthread_join() is to update the void *
given through its second argument in order to obtain the result of the
thread function (a void *).
When you need to update an int as in scanf("%d", &my_var); the argument
is the address of the int to be updated: an int *.
With the same reasoning, you update a void * by providing a void **.
In the specific situation of your example, we don't use the returned
void * in a normal way: this is a trick!
Since a pointer can be thought about as a big integer counting the bytes in
a very long row, the trick is to assume that this pointer can simply store
an integer value which does no refer to any memory location.
In your example, returning (void *)42, is equivalent to saying
"you will find something interesting at address 42".
But nothing has ever been placed at this address!
Is this a problem? No, as long as nobody tries to dereference this
pointer in order to retrieve something at address 42.
Once pthread_join() has been executed, the variable res has
been updated and contains the returned void *: 42 in this case.
We perform here the reverse-trick by assuming that the information memorised
in this pointer does not refer to a memory location but is a simple integer.
It works but this is very ugly!
The main advantage is that you avoid the expensive cost of malloc()/free()
void *myThread(void *arg)
{
int *result=malloc(sizeof(int));
*result=42;
return result;
}
...
int *res;
pthread_join(tid, &res);
int result=*res; // obtain 42
free(res);
A better solution to avoid this cost would be to use the parameter
of the thread function.
void *myThread(void *arg)
{
int *result=arg;
*result=42;
return NULL;
}
...
int expected_result;
pthread_create(&tid, NULL, myThread, &expected_result);
pthread_join(tid, NULL);
// here expected_result has the value 42
I would like to pass a parameter from my main() into my function. Please let me know how should I do that. I saw some methods in Internet but they didn't work.
Here is the code:
void *deliver(int *i)
{
int *ThreadID=(int *)tid;
//Here I would like to do some comparing on arrays using i parameter
//a[i]>b[i] As an example
}
void main ()
{
pthread_t t2_deliver[100];
//input var
printf("By using this code you can apply T threads on ordering list ;) \n");
printf("->*******************************************************************************<-\n");
printf("Please enter the number of threads(T):\n");
scanf("%d",&threadnum);
for (i=0; i<threadnum; i++)
{
pthread_create(&t2_deliver[i],NULL,deliver,&i);
}
You have a logical error in your code. All threads you create will have a pointer to the same i, meaning it will have the same value in all threads, and will most likely be out of bounds as the threads will run after the loop creating the threads.
One possible solution is to use casting and the standard intptr_t to pass the value to the thread functions:
pthread_create(..., (void*) (intptr_t) i);
And in the thread:
void *deliver(int *p)
{
int i = (int) (intptr_t) p;
...
}
First error that I see is you try to cast not what is in i (argument of function) but in some variable tid.
In principle thread function (in your case deliver) accepts as an argument void pointer, which later can be casted to what you sent, so just to play by the rules I would recommend you that you change function definition so it accepts void pointer as argument, not int pointer. It should not make any difference but is more correct. Why is this better: void pointer is a pointer to some data we don't know yet what it is so we need to cast it in function, this gives us the freedom that we could pass to function whatever we want from simple integers to complex structures. If you then want to get the value that is stored on location passed as function argument you dereference it with * operator. So I'm suggesting you make this modifications, thread function should look something like this:
void *deliver(void *i){
// in p there is integer pointer to argument i
int *p = (int *)i;
// now in ThreadID we have value of argument we passed to function in main (value at address i)
int ThreadID = *p;
//Here I would like to do some comparing on arrays using i parameter
//a[i]>b[i] As an example
}
and when creating threads just to do it right I would do this:
pthread_create(&t2_deliver[i],NULL,deliver,(void *)&i);
Maybe some of the things like type of pointer are not necessary but I think it is more correct and by my experience this works fine and you get the freedom to pass to function everything you want if you then cast it and dereference it correctly. Hope this helps.
Update and fix:
As mentioned in a comment below by Jonathan Leffler passing address of i in for loop (main function) is wrong, because then all threads point with their arguments to the same integer i in memory and effectively to the same value. There are plenty of workarounds, two are mentioned below by Jonathan Leffler, my favourite is constructing array of ids and then assagning and sending each id in array to each of threads:
ind tid[100];
for (int i = 0; i < 100; i++){
tid[i] = i;
pthread_create(&t2_deliver[i],NULL,deliver,(void *)&tid[i]);
}
Sorry for my mistake.
I'm not sure if the question has asked before, but I couldn't find any similar topics.
I'm struggeling with the following piece of code. The idea is to extend r any time later on without writing lots of if-else statements. The functions (func1, func2...) either take zero or one arguments.
void func1() {
puts("func1");
}
void func2(char *arg){
puts("func2");
printf("with arg %s\n", arg);
}
struct fcall {
char name[16];
void (*pfunc)();
};
int main() {
const struct fcall r[] = {
{"F1", func1},
{"F2", func2}
};
char param[] = "someval";
size_t nfunc = RSIZE(r); /* array size */
for(;nfunc-->0;) {
r[nfunc].pfunc(param);
}
return 0;
}
The code above assumes that all functions take the string argument, which is not the case. The prototype for the pointer function is declared without any datatype to prevent the incompatible pointer type warning.
Passing arguments to functions that do not take any parameters usually results in too few arguments. But in this case the compiler doesn't 'see' this ahead, which also let me to believe that no optimization is done to exclude these unused addresses from being pushed onto the stack. (I haven't looked at the actual assemble code).
It feels wrong someway and that's usually a recipe for buffer overflows or undefined behaviour. Would it be better to call functions without parameters separately? If so, how much damage could this do?
The way to do it is typedef a function with 1 argument, so the compiler could verify if you pass the correct number of arguments and that you do not pass something absolutely incompatible (e.g. a struct by value). And when you initialize your array, use this typedef to cast function types.
void func1(void) { ... }
void func2(char *arg) { ... }
void func3(int arg) { ... }
typedef uintptr_t param_t;
typedef void (*func_t)(param_t);
struct fcall {
char name[16];
func_t pfunc;
};
const struct fcall r[] = {
{"F1", (func_t) func1},
{"F2", (func_t) func2}
{"F3", (func_t) func3}
};
...
r[0].pfunc((param_t) "foo");
r[1].pfunc((param_t) "bar");
r[2].pfunc((param_t) 1000);
Here param_t is defined as uintpr_t. This is an integer type big enough to store a pointer value. For details see here: What is uintptr_t data type.
The caveat is that the calling conventions for param_t should be compatible with the function arguments you use. This is normally true for all integer and pointer types. The following sample is going to work, all the type conversions are compatible with each other in terms of calling conventions:
// No problem here.
void ptr_func(struct my_struct *ptr) {
...
}
...
struct my_struct struct_x;
((func_t) &ptr_func)((param_t) &struct_x);
But if you are going to pass a float or double argument, then it might not work as expected.
// There might be a problem here. Depending on the calling
// conventions the value might contain a complete garbage,
// as it might be taken from a floating point register that
// was not set on the call site.
void float_func(float value) {
...
}
...
float x = 1.0;
((func_t) &float_func)((param_t) x);
In this case you might need to define a function like this:
// Problem fixed, but only partially. Instead of garbage
// there might be rounding error after the conversions.
void float_func(param_t param) {
float value = (float) param;
...
}
...
float x = 1.234;
((func_t) &float_func)((param_t) x);
The float is first being converted to an integer type and then back. As a result the value might be rounded. An obvious solution would be to take an address of x and pass it to modified a function float_func2(float *value_ptr). The function would dereference its pointer argument and get the actual float value.
But, of course, being hardcore C-programmers we do not want to be obvious, so we are going to resort to some ugly trickery.
// Problem fixed the true C-programmer way.
void float_func(param_t param) {
float value = *((float *) ¶m);
...
}
...
float x = 1.234;
((func_t) &float_func)(*((param_t *) &x));
The difference of this sample compared to passing a pointer to float, is that on the architecture (like x86-64) where parameters are passed on registers rather than on the stack, a smart enough compiler can make float_func do its job using registers only, without the need to load the parameter from the memory.
One option is for all the functions accept a char * argument, and your calling code to always pass one. The functions that don't need an argument need not use the argument they receive.
To be clean (and avoid undefined behaviour), if you must have some functions that accept no argument and some functions that accept an argument, use two lists and register/call each type of function separately.
If the behaviour is undefined there's no telling how much damage could be caused.
It might blow up the planet. Or it might not.
So just don't do it, OK?
Even though it is possible to write generic code in C using void pointer(generic pointer), I find that it is quite difficult to debug the code since void pointer can take any pointer type without warning from compiler.
(e.g function foo() take void pointer which is supposed to be pointer to struct, but compiler won't complain if char array is passed.)
What kind of approach/strategy do you all use when using void pointer in C?
The solution is not to use void* unless you really, really have to. The places where a void pointer is actually required are very small: parameters to thread functions, and a handful of others places where you need to pass implementation-specific data through a generic function. In every case, the code that accepts the void* parameter should only accept one data type passed via the void pointer, and the type should be documented in comments and slavishly obeyed by all callers.
This might help:
comp.lang.c FAQ list ยท Question 4.9
Q: Suppose I want to write a function that takes a generic pointer as an argument and I want to simulate passing it by reference. Can I give the formal parameter type void **, and do something like this?
void f(void **);
double *dp;
f((void **)&dp);
A: Not portably. Code like this may work and is sometimes recommended, but it relies on all pointer types having the same internal representation (which is common, but not universal; see question 5.17).
There is no generic pointer-to-pointer type in C. void * acts as a generic pointer only because conversions (if necessary) are applied automatically when other pointer types are assigned to and from void * 's; these conversions cannot be performed if an attempt is made to indirect upon a void ** value which points at a pointer type other than void *. When you make use of a void ** pointer value (for instance, when you use the * operator to access the void * value to which the void ** points), the compiler has no way of knowing whether that void * value was once converted from some other pointer type. It must assume that it is nothing more than a void *; it cannot perform any implicit conversions.
In other words, any void ** value you play with must be the address of an actual void * value somewhere; casts like (void **)&dp, though they may shut the compiler up, are nonportable (and may not even do what you want; see also question 13.9). If the pointer that the void ** points to is not a void *, and if it has a different size or representation than a void *, then the compiler isn't going to be able to access it correctly.
To make the code fragment above work, you'd have to use an intermediate void * variable:
double *dp;
void *vp = dp;
f(&vp);
dp = vp;
The assignments to and from vp give the compiler the opportunity to perform any conversions, if necessary.
Again, the discussion so far assumes that different pointer types might have different sizes or representations, which is rare today, but not unheard of. To appreciate the problem with void ** more clearly, compare the situation to an analogous one involving, say, types int and double, which probably have different sizes and certainly have different representations. If we have a function
void incme(double *p)
{
*p += 1;
}
then we can do something like
int i = 1;
double d = i;
incme(&d);
i = d;
and i will be incremented by 1. (This is analogous to the correct void ** code involving the auxiliary vp.) If, on the other hand, we were to attempt something like
int i = 1;
incme((double *)&i); /* WRONG */
(this code is analogous to the fragment in the question), it would be highly unlikely to work.
Arya's solution can be changed a little to support a variable size:
#include <stdio.h>
#include <string.h>
void swap(void *vp1,void *vp2,int size)
{
char buf[size];
memcpy(buf,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buf,size); //memcpy ->inbuilt function in std-c
}
int main()
{
int array1[] = {1, 2, 3};
int array2[] = {10, 20, 30};
swap(array1, array2, 3 * sizeof(int));
int i;
printf("array1: ");
for (i = 0; i < 3; i++)
printf(" %d", array1[i]);
printf("\n");
printf("array2: ");
for (i = 0; i < 3; i++)
printf(" %d", array2[i]);
printf("\n");
return 0;
}
The approach/strategy is to minimize use of void* pointers. They are needed in specific cases. If you really need to pass void* you should pass size of pointer's target also.
This generic swap function will help you a lot in understanding generic void *
#include<stdio.h>
void swap(void *vp1,void *vp2,int size)
{
char buf[100];
memcpy(buf,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buf,size); //memcpy ->inbuilt function in std-c
}
int main()
{
int a=2,b=3;
float d=5,e=7;
swap(&a,&b,sizeof(int));
swap(&d,&e,sizeof(float));
printf("%d %d %.0f %.0f\n",a,b,d,e);
return 0;
}
We all know that the C typesystem is basically crap, but try to not do that... You still have some options to deal with generic types: unions and opaque pointers.
Anyway, if a generic function is taking a void pointer as a parameter, it shouldn't try to dereference it!.