Thread struct as function parameter C

12,578

Solution 1

I recommend you to read http://www.advancedlinuxprogramming.com/alp-folder/alp-ch04-threads.pdf

And here what you wanted:

 #define N 5 
typedef struct thread {   
     pthread_t thread_id;       
     int       thread_num;
     // int       thread_sum;       
} ThreadData;
void *thread_start(void *thread)
{
   ThreadData *my_data  = (ThreadData*)thread;
   //there is no guarantee that prints will be in order
   //  we will use its initial thread->num ,cause it differs for each thread
   //plus you will see how threads will behave
   int order=my_data->thread_num;
   printf("%i) before num T: %i\n",order, my_data->thread_num);
   my_data->thread_num=4;
   printf("%i) after assignment num T: %i\n",order ,my_data->thread_num);

   return NULL;
}

int main(int argc, char *argv[])
{
   int i;
   ThreadData thread[N]; 
   for(i=0; i<N; i++)
   {
      thread[i].thread_num=i;
     pthread_create(&(thread[i].thread_id), NULL, thread_start, (void *)(thread+i));

   }
   //wait for all threads
   for (i = 0; i < N; i++)
       pthread_join(thread[i].thread_id, NULL); 
   //print results of each thread
   for (i = 0; i < N; i++)
       printf(" %i)thread: number %i\n",i,thread[i].thread_num);
   return 0;
}

Solution 2

I can see multiple mistakes in your code.

First you have your pointers wrong. In the first example, it is enough to pass &pthread_data to pthread_create, &thread is the address of the thread pointer, so you are passing struct thread ** to your function instead of struct thread *. In the second example you should use (void *) thread[i]. &thread[i] is again struct thread **.

When you want each thread to write to its own thread data, then you should make an array of thread data, so that each thread has its own piece, else you will run into race conditions.

As others have already pointed out, you should call pthread_join before calling printf to ensure that the main thread will wait for all worker threads.

Also note that if you are calling pthread_join from other function that the one that spawned those threads, you have to ensure that the array of tread data will not go out of scope (in this case it would be probably better to use malloc or a global array).

Share:
12,578

Related videos on Youtube

ganlub
Author by

ganlub

I am a freelance developer who believes in smart coding and beautiful design. I show my passion for every project in the websites and applications I build.

Updated on September 29, 2022

Comments

  • ganlub
    ganlub over 1 year

    I'm having a trouble passing a struct pointer into a function because I'm a bit confused with those pointers and references. I want to modify the thread.thread_num value from the thread_startfunction.

    #include <stdio.h>
    #include <stdlib.h> //malloc, free
    #include <pthread.h>
    
    #define N 5
    
    // void    *malloc(size_t);
    
    struct thread {   
         pthread_t thread_id;       
         int       thread_num;
         // int       thread_sum;       
    };
    
    void *thread_start(void *thread)
    {
       struct thread *my_data;
       my_data = (struct thread *)thread;
       printf("num T: %i\n", my_data->thread_num);
       my_data->thread_num=4;
       printf("num T: %i\n", my_data->thread_num);
    
       return NULL;
    }
    
    int main(int argc, char *argv[])
    {
       int i;
       struct thread  pthread_data;
       struct thread *thread = &pthread_data;
    
       thread->thread_num=2;
       pthread_create(&thread->thread_id, NULL, thread_start, (void *)&thread);
       printf("num: %i\n",thread->thread_num);
    
       pthread_exit(NULL);
       return 0;
    }
    

    But the value that print the main doesn't change (2).

    And then I want to create an array of thread struct, but I don't know how exactly do that: I guess it should be something like this:

    int main(int argc, char *argv[])
    {
       int i;
       struct thread  pthread_data;
       struct thread *thread[N-1] = &pthread_data; // I don't know how to manage this.
       for(i=0; i<N; i++)
       {
       thread->thread_num=i;
       pthread_create(&thread[i]->thread_id, NULL, thread_start, (void *)&thread[i]);
       printf("num %i: %i\n",i,thread[i]->thread_num);
       }
       pthread_exit(NULL);
       return 0;
    }
    

    Any thoughts?

  • hyde
    hyde over 10 years
    It's not this, but a simple race condition, main prints before the thread modifies.
  • David Schwartz
    David Schwartz over 10 years
    @hyde He has a race condition, but this is the answer to his question.
  • hyde
    hyde over 10 years
    "But the value that print the main doesn't change" part certainly happens before the pointer in the thread becomes dangling.
  • David Schwartz
    David Schwartz over 10 years
    @hyde Maybe, maybe not. It's undefined behavior, so it's hard to be sure. I took "I want to modify the thread.thread_num value from the thread_startfunction." as his primary question, and the answer is that he can't because it's not guaranteed to exist.
  • hyde
    hyde over 10 years
    Well, this is getting argumentative, but... fixing the race condition would implicitly fix the dangling pointer UB, but fixing just the danging pointer UB would not necessarily change the output. But the main thing I object is implying, that using local variables of main is problem. It is not, it's perfectly fine in a normal application. The problem is allowing main to exit while other threads are still running, not using main local variable.