Passing structures as arguments while using pthread_create()
Asked Answered
M

8

17

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?

Mastoiditis answered 14/5, 2009 at 15:15 Comment(0)
S
24

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 on the heap and pass that structure pointer 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 */
}
Sore answered 14/5, 2009 at 15:27 Comment(3)
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).Mastoiditis
Your recent edit was the most useful post here till now. Thanks.Mastoiditis
Bacon is worth saving.Sore
Q
2

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 */
}
Qktp answered 14/5, 2009 at 15:22 Comment(4)
I did that but now I get a "dereferencing 'void *' pointer" error.Mastoiditis
Harper meant to write: my_struct foo = *(my_struct *)arg; or my_struct *foo = (my_struct *)arg;Esprit
Used this idea and Lyndsey Ferguson's edit posted - May 14th, 2009 @ 12:19 PM EST.Mastoiditis
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.Qktp
V
1
  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

Vadose answered 15/5, 2009 at 9:50 Comment(0)
C
0

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.

Cecillececily answered 14/5, 2009 at 15:21 Comment(0)
M
0

This error message means you're not dereferencing the pointer.

You're saying "t.a" instead of "t->a"

[me@myhost ~]$ cat testitx.c
struct x {
        int a, b;
};

int main(int argc, char *argv[])
{
        struct x y, *z;

        z = &y;
        z.a = 10;
}
[me@myhost ~]$ cc -c testitx.c
testitx.c: In function `main':
testitx.c:10: error: request for member `a' in something not a structure or union
[me@myhost ~]$
Mortimer answered 14/5, 2009 at 15:34 Comment(1)
Doesn't help. I used Harper Shelby's solution to get a "dereferencing 'void *' pointer" error.Mastoiditis
I
0

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.

Inductee answered 14/5, 2009 at 15:55 Comment(2)
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...Starryeyed
I don't understand how this helps solve my problem. Those casts you've used are way too cryptic.Mastoiditis
M
0

my_struct foo = (my_struct)(*arg); is incoreect try my_struct *foo = (my_struct *)(arg);
AND, int the function Calling the thread, make sure its static (so the memory being pointed to, is not lost in the fog)

Mcevoy answered 25/7, 2014 at 18:32 Comment(0)
T
0

Here is an example : This the function that will create the thread and pass the struct param

pthread_create (& threads[i], NULL , PrintMessage ,(void *) &tab[i]);

And this is the thread function :

 void *PrintMessage(void * arg)
{
struct param *mes_param ; mes_param = (struct param*) arg;
printf (" message from thread %d: %s\n", mes_param -> num_message ,
mes_param -> message );
pthread_exit(NULL);
}

Struct :

struct param {
int num_message ;
char* message ; };
struct param tab[MAX_THREADS];
Trinitroglycerin answered 17/3, 2021 at 15:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.