Request Scheduling using Threads and Synchronization
In this assignment, we will use threads and synchronization to
implement the Producer Consumer and the Bounded Buffer
problem studied in class. This lab needs to be completed
in C/C++ using the pthreads library with the overall goal of exposing you to threading
and synchronization concepts.
The goal of the lab is to first implement a bounded buffer class and then use it
to implement the producer consumer problem. The first step is to implement a bounded
buffer using synchronization. First review lecture 9 slides (specifically page 25 that
describes the Bounded buffer implementation). Using these concepts, implement a bounded
buffer class using pthreads mutex (i.e., locks) and condition variables. The constructor
for your bounded buffer class should take N as an input and instantiate an integer
array of size N. Assume that the bounded buffer contains integer data items.
As shown in the lecture slides, the bounded buffer is a circular buffer. Upon reaching the end of the buffer array, your code should cycle back to the start of the array to add new data items to the circular buffer. Items are always added to the tail of the buffer and removed from the head of the buffer
Keep in mind that page 25 of lecture 9 showed a Hoare-style monitor implementation, while pthreads condition variables use Mesa-style implementation.
Next implement a ProducerConsumer class that uses this Bounded Buffer to produce and consumer data. Your class should have two main methods: a producer() method where a producer thread sits in a loop and in each iteration, it first sleeps for a specified duration, then produces a data item (the data item in this case is a integer with a random value), and calls the add method of the bounded buffer to add the data item to the buffer.
In the consumer() method, a consumer thread sits in a loop, and first sleeps for a specified duration and then calls the remove method of the bounded buffer to remove an item from the circular buffer.
The constructor for the ProducerConsumer class takes several inputs:
Given these inputs, the constructer method should create p producer threads, each of which start in the producer() method, and c consumer threads, each of which start in the consumer() method. After producer a data item, a producer thread should increment a shared integer variable. When this variable reaches item, all producer and consumer threads should quit (of course the consumer threads should consume all items in the buffer as well before quitting).
Note that the bulk of the syncronization is done in the bounded buffer class, while the bulk of thread management is done in the producer consumer class (if you use any shared variables in producers and consumers, be sure to use syncronization to protect those variables as well).
Your producer and consumer methods should print the following messages to a file called "output.txt"
Producer #i, time = current time, producing data item #j, item value=foo
Consumer #k, time = current time, consuming data item with value=foo
Helpful references IF you are not familiar with pthreads, be sure to review this reference on Pthreads programming. A brief tutorial is also available.
Discussion 5 included a tutorial on using the gdb debugger to debug your code. Compile your code with the -g flag to enable debugging. Start your program using gdb. Set breakpoints to pause execution and examine variables. Step execute your code one statement at a time. Briefly document your experience with gdb and explain if it helped you fix a bug. Since gdb can be tricky to use multi-threaded code that may run differently, explain other methods you tried to figure out bugs in your code (e.g., using print statements or finding memory leaks using valgrind etc).
Testing and debugging can be done on the Edlab machines if you do not have a debugger or the GTest testing framework installed on your personal machine.
Once you have written your version of the shell, write a design document that documents your design choices. The design doc should be written in plain text in a file called README.txt.
The README file should also document observations from running your code with various inputs as explained above and your experience with testing / debugging and the test case you wrote.
We will use the gradescope autograder system to submit and grade your assignment.
It is important that you keep the directory structure the same as what we have given to you in the starter code. You may not be able to receive a grade otherwise.To submit your code to gradescope, you need to create a zip file and upload it through your gradescope account. Your should zip your src and test folders directly into a zip file (do not zip the parent directory). You can use the following command: zip -r mycode.zip src test to create the zip file, or use any GUI based method or zip program to create the zip file. For example, on a Mac, select the src and test directory using the command key and then right click to select "Compress two items".
Once you upload to gradescope, it will run some tests and let you know how many tests passed or if your code failed to complile or failed to terminate. While we will not reveal the test cases, we will give you brief indication of the type of tests that failed on your code to help you understand what may be going wrong. You can submit as many times as you wish to gradescope until the deadline or until your code passes all tests.
You should be very careful about using code snippets you find on the Internet. In general your code should be your own. It is OK to read tutorials on the web and use these concepts in your assignment. Blind use of code from web is strictly disallowed. Feel free to check with us if you have questions on this policy. And be sure to document any Internet sources/ tutorials you have used to complete the assignment in your README file.
(max 100) Total Grade