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):
ex17.cc
,
which contains the producer and consumer functionsSimpleQueue.h
,
the header file for SimpleQueue
, a linked list queue that is used as the producer-consumer bufferSimpleQueue.cc
,
the implementation of SimpleQueue
Makefile
,
a makefile that will build the ex17
program (you should not change this file)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:
ex17
using the supplied
Makefile
cpplint
may be helpful in flagging potential style
problems. (You can ignore cpplint
complaints about
using namespace
directives, as well as
<thread>
or <chrono>
being unapproved C++ headers)
You should submit your exercise to the course Gradescope.