In your group you are going to do the following:
- On paper, come up with a PSEUDOCODE solution to synchronize the
actions of Producer and Consumer threads that add and remove items to
a shared, fixed-capacity buffer:
- Some number of Producer threads, each in a loop forever:
- produce the next item
- add it to the shared buffer (to one end of a circular queue)
- Some number of Consumer threads, each in a loop forever:
- remove the next item from the front of the buffer
- consume it
Some questions to consider:
- are there actions that need to be made atomic
(require mutually exclusive access)?
- are there any scheduling types of synchronization necessary?
- what synchronization primitives do you need?
and how are they used (by whom and when)?
- is any other state needed to synchronize the actions of threads?
You may assume:
- The following shared global buffer state has been declared:
static char *buff; // the buffer
static int N; // total buffer capacity
static int size; // current num items in the buffer
static int next_in; // next insertion index in the buffer
static int next_out; // next remove index in the buffer
static int num_items; // number of items each tid should produce or consume
- There exist functions to add and remove items to the buffer as
a circular queue (add to one end, remove from the other).
void add_to_queue(char item);
char remove_from_queue();
These functions have no synchronization, nor do they check if there is space
on an add or something to remove on a remove. They just add or remove
to buff in a circular fashion and update other state variables as a
result of their actions.
- Some pthread functions:
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
pthread_cond_wait(&mycond, &mutex);
pthread_cond_signal(&mycond);
pthread_barrier_init(&mybarrier, NULL, numtids);
pthread_barrier_wait(&mybarrier);
- When you are happy with your pseudocode algorithm, let me know. If I'm with another group, talk with your neighbors and see how they're doing.