Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>OK here's part of my solution, it's missing most of main, and has some other simple stuff missing, if you choose to base your code around this you can do one of two things load all the data before starting your workers, or have the main thread load it while the workers are running, I did the latter in my complete version. However you'll have to do some work to get that to be handled correctly because currently the workers will never exit.</p> <p>Also you might want to try adapting your single array code above based on this.</p> <p>So if you load all the data before starting the workers you don't need the condition variable and they can just exit when <code>next_chunk</code> is <code>NULL</code>. I recommend you figure out how to get loading while the workers are running working because it'll be more efficient. Hint: <code>pthread_cond_broadcast()</code></p> <p>Also missing is the actual worker function.</p> <pre><code>// A singly linked list of chunks of 1000 numbers // we use it as a queue of data to be processed struct number_chunk { struct number_chunk *next; int size; int nums[1000]; }; pthread_mutex_t cnklst_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t data_available = PTHREAD_COND_INITIALIZER; struct number_chunk *next_chunk = NULL; void load_chunks(char *filename) { FILE *in = fopen(filename, "r"); int done = 0; int i; if(in == NULL) { fprintf(stderr, "Failed to open file %s\n", filename); return; } // read in all the chunks of 1000 numbers from the file while(!done) { struct number_chunk *cnk = malloc(sizeof(struct number_chunk)); // allocate a new chunk cnk-&gt;next = NULL; for(i=0; i &lt; 1000; i++) { // do the actual reading char tmp[20]; if(fgets(tmp, 20, in) == NULL) { // end of file, leave the read loop done = 1; break; } cnk-&gt;nums[i] = atoi(tmp); } // need to do this so that the last chunk in a file can have less than 1000 numbers in it cnk-&gt;size = i; // add it to the list of chunks to be processed pthread_mutex_lock(&amp;cnklst_mutex); cnk-&gt;next = next_chunk; next_chunk = cnk; pthread_cond_signal(&amp;data_available); // wake a waiting worker pthread_mutex_unlock(&amp;cnklst_mutex); } fclose(in); } struct number_chunk *get_chunk() { struct number_chunk *cnk = NULL; pthread_mutex_lock(&amp;cnklst_mutex); //FIXME: if we finish we will never exit the thread // need to return NULL when all the work that there will ever be // is done, altertitively load everything before starting the workers and // get rid of all the condition variable stuff while(next_chunk == NULL) pthread_cond_wait(&amp;data_available, &amp;cnklst_mutex); cnk = next_chunk; if(next_chunk != NULL) next_chunk = next_chunk-&gt;next; pthread_mutex_unlock(&amp;cnklst_mutex); return cnk; } </code></pre> <p>The way my workers report the final max prime is to just do it at the end by looking at a single global variable and setting it or not based on the highest prime they found during their run. Obviously you'll need to synchronize for that.</p> <p>Also note it uses a mutex rather than a semaphore because of the use of <code>pthread_cond_wait()</code> If you haven't covered condition variables yet just drop that stuff and load everything before starting your workers.</p> <p>Also since this is homework, read my code try to understand it then without looking at it again try to write your own.</p> <p>I would have changed it more but I'm not sure how because it's already basically a really generic producer/consumer example that's missing some bits :P</p> <p>Another thing to try if you do decide to adopt the same strategy I did and have the loading running in the main thread while the workers work you could add a second condition variable and a counter to limit the number of chunks in the queue and have your workers wake up the main thread if they run out of work.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload