views:

3653

answers:

6

I tried passing a structure as the 4th argument while using pthread_create() with something like this:

pthread_create(&tid1, NULL, calca, &t); //t is the struct

Now whenever I try to access variables in the structure - t.a, t.b or t.c, I keep getting an error - request for member in something not a structure or union.

What alternate method could I use to pass structs into the thread?

A: 

You could use shared memory or a global variable, (if nothing else will need that argument) or a linkedlist if these are threads that are feeding off of data.

Just remember to lock your variables that are being thread-shared.

Without the actual offending code though, i can't tell you what you're doing wrong in your current implementation.

cyberconte
Removed down vote due to expansion of the answer.
Harper Shelby
+1  A: 

If you're inside your thread function, the argument you pass is a void*. You'll need to cast it to a struct before you can use it as such.

void my_thread_func(void* arg){
    my_struct foo = (my_struct)(*arg); /* Cast the void* to our struct type */
    /* Access foo.a, foo.b, foo.c, etc. here */
}
Harper Shelby
I did that but now I get a "dereferencing 'void *' pointer" error.
skinderneath
Harper meant to write: my_struct foo = *(my_struct *)arg; or my_struct *foo = (my_struct *)arg;
Jonathan Leffler
Used this idea and Lyndsey Ferguson's edit posted - May 14th, 2009 @ 12:19 PM EST.
skinderneath
Yeah, c-style casts aren't my strong point, and it's been a few years since I used pthread_create. I prefer C++ and a good threading library.
Harper Shelby
+3  A: 

You're probably creating the structure in the same scope as pthread_create. This structure will no longer be valid once that scope is exited.

Try creating a pointer to the structure and pass that structure to your thread. Don't forget to delete that memory somewhere (in the thread if you'll never use it again - or when you no longer need it).

Also, as cyberconte mentioned, if you are going to be accessing that data from different threads, you'll need to lock access to it with a mutex or critical section.

Edit May 14th, 2009 @ 12:19 PM EST: Also, as other people have mentioned, you have to cast your parameter to the correct type.

If you are passing a variable that is a global structure (which you seem to be insisting upon), your thread function will have to cast to the type:

void my_thread_func(void* arg){
    my_struct foo = *((my_struct*)(arg)); /* Cast the void* to our struct type */
    /* Access foo.a, foo.b, foo.c, etc. here */
}

Or, if you are passing a pointer to your structure:

void my_thread_func(void* arg){
    my_struct* foo = (my_struct*)arg; /* Cast the void* to our struct type */
    /* Access foo->a, foo->b, foo->c, etc. here */
}
Lyndsey Ferguson
Actually, I created the thread in the main function and created the structure right after including the header files. So it should be accessible by all functions(correct me if I'm wrong).
skinderneath
Your recent edit was the most useful post here till now. Thanks.
skinderneath
A: 
Doesn't help. I used Harper Shelby's solution to get a "dereferencing 'void *' pointer" error.
skinderneath
A: 

I often used to make the same mistakes listed in the other answers, but now I take a slightly different approach that moves the potential for error from the threading function to the pthread_create call.

I declare and define the threading function in a 'normal' way:

void *ThreadFunction(sPARAMETERS *Params) {

  // do my threading stuff...

}

and when I call pthread_create, I need to use a cast:

pthread_create(&ThreadId,0,(void*(*)(void*)) &ThreadFunction,&Params);

I almost never forget to use the & on the Params, and the compiler will take care of any mistakes I make on the other end. Works great for callbacks, too.

Marc Bernier
Technically speaking, this is undefined behavior - although on most compilers it will work for ordinary structure pointers. Don't try it with C++ member function pointers...
bdonlan
I don't understand how this helps solve my problem. Those casts you've used are way too cryptic.
skinderneath
+1  A: 
  1. Create a semaphore

  2. Create another structure that consists of a pointer to your structure and the semaphore handle

  3. Pass a pointer to this new structure to pthread_create

  4. In the parent thread, i.e. that called pthread_create, wait on the semaphore

  5. In the child thread, copy members of your structure to local variables or save them elsewhere

  6. In the child thread, signal the semaphore

  7. In the parent thread, close the semaphore

dmityugov