I want all threads to read from the same structure. I did it in the past by adding threads inside the loop which reads from the structure but this time I need the structure to be opened inside void "dowork" as my example shows.
I have the following code:
struct word_list {
char word[20];
struct word_list * next;
};
struct word_list * first_word = NULL;
//other function which loads into struct is missing cause it's not relevant
//in main()
pthread_t thread_id[MAX_THREADS];
int max_thread = 10;
for(t = 0 ; t < max_thread; t++)
{
pthread_mutex_lock(&thrd_list);
arg_struct *args = calloc(1, sizeof(*args));
args->file = file;
args->t = t;
args->e = ex;
pthread_mutex_unlock(&thrd_list);
if(pthread_create(&thread_id[t],NULL,dowork,args) != 0)
{
t--;
fprintf(stderr,RED "\nError in creating thread\n" NONE);
}
}
for(t = 0 ; t < max_thread; t++)
if(pthread_join(thread_id[t],NULL) != 0)
{
fprintf(stderr,RED "\nError in joining thread\n" NONE);
}
void *dowork(void *arguments)
{
struct word_list * curr_word = first_word;
char myword[20];
while( curr_word != NULL )
{
pthread_mutex_lock(&thrd_list);
strncpy(myword,curr_word->word,sizeof(myword) - 1);
pthread_mutex_unlock(&thrd_list);
//some irrelevant code is missing
pthread_mutex_lock(&thrd_list);
curr_word = curr_word->next;
pthread_mutex_unlock(&thrd_list);
}
}
How can I read different elements from the same structure in all threads?
So you want to process lots of data by splitting the work across multiple threads. Your solution is not very efficient because your threads are going to be fighting a lot of who owns the mutex and you can't be sure the work is evenly spread across all your threads. So, for example, threads 0 and 1 could be getting all the work as they get first access to the mutex and all the other threads are just idle all the time.
If you want to improve the performance, you need to do the following:-
So, in your program, instead of a single linked list that is shared across all threads, have a linked list for each thread:-
In this program (just made it up, haven't checked it) I create four linked lists and evenly assign data to the lists. Then I create the threads and give each thread one of the linked lists. Each thread then processes its own linked list (they are separate lists).
Each thread can now run at full speed and never has to wait on a mutex to get data. Memory accesses are reasonable but dependent on the allocator to a large extent. Using an array rather than a linked list would improve this, but you'd need to know the number of data items before allocating the arrays which might not be possible.
If I understand your requirements now (and I think I finally do), you need to treat your word list as a work queue. To do that requires a notification mechanism that allows the "pusher" of items into the queue to inform the "pullers" that new data is available. Such a system does exist in pthreads: the marriage of a condition variable, a mutex, and the predicate(s) they manage for control flow.
This is one example of how to use it. I've tried to document what is going on at each step for you, and hopefully you will understand.
Sample Output: MAX_THREADS = 4 (your output will vary)
Sample Output: MAX_THREADS = 8
Sample Output: MAX_THREADS = 16
And just because we can, with full global optimization enabled
Sample Output: MAX_THREADS = 32, MAX_ITEMS = 4194304
Hmmm. and I didn't use
volatile
in any of this. Must be time to buy a lotto ticket.Anyway, I suggest doing some research on pthreads, particularly on mutex and condition variable control and their interactions. I hope this helps you out.
Let me see if i understand this correctly?
struct word_list
describes some kind of linked listIf this is what you want then I would just pop the elements one by one from the list and write the pointer to the rest back:
Make an additional global
volatile struct word_list * next_word
if you don't want to modifyfirst_word
. Make sure to make itvolatile
, else the compiler may perform optimisations that lead to weird results.