CSE 333 24su Exercise 17

Due:Monday, August 12th, 2024 by 10:00 am; No late exercises accepted.
Goals:Use pthreads to modify an existing queue data structure to be thread-safe, and modify a sequential client program to produce and consume pies concurrently.

A common design pattern used in concurrent programming is called the Producer-Consumer pattern. In this design there is a set of producers that generate work for a set of consumers. As the producers create work items, they place them into a buffer. When a consumer is free to process a new work item, it grabs the next one from the buffer. For this exercise you should take the initial version of the program, where the producers run sequentially followed by the consumer, and change it so the producers and consumer run concurrently.

You should start by downloading the following four files (right-click if needed):

Looking in the main function in ex17.cc, you can see that the program starts a producer of apple pies, and then it starts a producer of blackberry pies, followed by a consumer that eats all the pies produced. Since this code runs sequentially and not concurrently, if you run the program you'll see that all the apple pies are produced first, followed by all the blackberry pies, and then all the pies are eaten.

Your job is to make the two producers and the consumer tasks run concurrently. This should be done for this exercise using pthreads (not C++11 threads). When the producers and consumer are run concurrently, the output of the program should change. For example, instead of all the pies being made first and then all eaten, some apple pies could be made, a few could be eaten, and then a blackberry pie could be made and immediately eaten. Each producer should create its pies and add them to the queue as they are created. The consumer should remove pies from the queue and eat them. If no pies are present in the queue when the consumer is ready to eat another one, it should wait a short while, then check again to see if a new pie is available.

In order for the producers and consumers to run concurrently without stepping on each other toes, you will need to make SimpleQueue thread-safe by modifying it so it acquires a lock when it runs critical sections of code and releases it when the critical section finishes. A critical section of code is any section where a resource shared among threads is accessed. If critical sections are not protected by locks, bad things such as data races and data structure corruption can occur. You should use a pthread mutex for this part.

Once SimpleQueue is thread safe, you should change ex17.cc so that the producers and consumer run concurrently. To do this you should use pthreads (discussed in section). You should not modify the given producer or consumer functions. Instead, you should create wrapper functions that allow you to start threads that then call the desired producer/consumer function.

Hint: Your code will probably use the following pthread calls: pthread_mutex_init(), pthread_mutex_destroy(), pthread_mutex_lock(), pthread_mutex_unlock(), pthread_exit(), pthread_join(), and pthread_create().

Hint: You may need to read up on the mutable keyword, because it could be necessary for making our const methods thread-safe.

Note: The producer and consumer functions contain code to pause (sleep) for a small amount of time each time a pie is created or consumed. This was done to introduce enough of a delay so that there would be some switching between threads in the concurrent version, rather than having each thread create or consume pies so quickly that we never see different execution orders or interleavings. As with the rest of the producer and consumer functions, you should not change this code.


As usual, your code must:

You should submit your exercise to the course Gradescope.