Write and Test Your Code
Time to write some code!
Remember that all of your work will be done in the file ringbuf.c.
- Start by opening up
ringbuf.cin your editor. Make sure that the names of both partners are included in comments at the top of the file. - Check the
ringbufSpecification for the details about what your code should do.
There are some hints further down in the page.
Compiling and Testing
We have provided a sample Makefile that will compile your program.
Pay attention to compiler warnings—and fix them!
To test your program, run it with standard input redirected to a test file. For example,
./ringbuf < testinput1.txt
The lab tar file includes five test files for you to try out:
testinput0.txt- A small test case with no sleeping. Note that because of
indeterminacy in the system scheduler, this test file may produce
different results from run to run. However, only it and
testinput4.txtwill ensure that you are interpretingprint_codecorrectly. testinput1.txt-
The test case from
testinput0.txt, with 1-second sleeps for the producer and no sleeping in the consumer. We recommend that you begin testing with this file, because it generates results that are easy to interpret. Also, be sure that it produces exactly one pair of output lines per second. If the output comes along too quickly, or if your program appears to hang, you may be callingnanosleepincorrectly. (Hint: if you runtime ./ringbuf < testinput1.txtit should report a “real” time of about 25 seconds.)
testinput2.txt- The test case from
testinput0.txt, with 1-second sleeps for the consumer and no sleeping in the producer. This file tests your ability to deal with situations where the producer runs far ahead of the consumer, so that the buffer is always full. testinput3.txt- A test case with randomly generated sleep times. At times, the producer will run ahead; at other times the consumer will catch up.
testinput4.txt- Another test case with randomly generated sleep times, and also
with randomly generated
print_codes.
We also provide two sample outputs; your output should match them exactly. You can check for correctness with the command
./ringbuf < testinput1.txt | diff testoutput1.txt -
and similarly for testinput2.txt. The diff command will be
silent if things match; otherwise it will tell you what lines are
different. Watch out for whitespace errors!
Sample Output
The following is the result of running our sample solution on the
test case testinput4.txt (note that your interleaving of
“Produced” and “Consumed” messages may differ, because this test input
has randomness built in):
Produced -8 from input line 2
Consumed 3 from input line 1; sum = 3
Produced 1 from input line 3
Produced 10 from input line 4
Consumed 1 from input line 3; sum = -4
Consumed 4 from input line 5; sum = 10
Produced 0 from input line 6
Consumed 0 from input line 6; sum = 10
Produced -1 from input line 8
Consumed -1 from input line 8; sum = 3
Consumed 8 from input line 9; sum = 11
Consumed 5 from input line 12; sum = 20
Produced 10 from input line 14
Consumed 1 from input line 15; sum = 40
Produced 10 from input line 16
Produced 5 from input line 17
Produced -2 from input line 20
Produced 1 from input line 21
Consumed -2 from input line 20; sum = 48
Consumed 9 from input line 23; sum = 53
Consumed 3 from input line 24; sum = 56
Produced 6 from input line 26
Consumed 6 from input line 26; sum = 55
Produced -3 from input line 27
Produced -8 from input line 32
Consumed -4 from input line 30; sum = 47
Consumed -7 from input line 31; sum = 40
Consumed -8 from input line 32; sum = 32
Consumed -4 from input line 34; sum = 34
Produced -7 from input line 36
Produced -1 from input line 39
Consumed 3 from input line 40; sum = 45
Consumed 1 from input line 41; sum = 46
Produced 10 from input line 42
Produced 0 from input line 43
Consumed -2 from input line 44; sum = 54
Produced -8 from input line 46
Consumed -8 from input line 46; sum = 39
Produced 1 from input line 49
Consumed -8 from input line 47; sum = 31
Consumed -1 from input line 48; sum = 30
Consumed 1 from input line 49; sum = 31
Consumed 11 from input line 50; sum = 42
Final sum is 42
Hints
Pthreads Features
You will need to familiarize yourself with the following pthreads functions, at a minimum:
pthread_createpthread_joinpthread_mutex_lockpthread_mutex_unlockpthread_cond_waitpthread_cond_signal
You may choose to use other functions as well. Remember that you are
NOT allowed to use the pthreads semaphore functions (sem_*).
Sleeping
For historical reasons, there are many ways to get a thread to go to
sleep for a specified time period. The preferred method is
nanosleep; see man 2 nanosleep for documentation. Note that
if the sleep time exceeds 999 milliseconds, you cannot simply
convert milliseconds to nanoseconds because nanosleep requires
that the nanoseconds field be less than \( 10^9 \). Also note that you
will not need the second argument to nanosleep; you can set it to
NULL. We have provided a wrapper function named thread_sleep
that accepts an argument in milliseconds and converts it into a
correct nanosleep call. However, note that as given, the wrapper
function does not work correctly: it always sleeps for 0.25 seconds.
You will have to modify it to calculate a correct value.
Also note that if the specified sleep time is zero, the wrapper function
doesn't call nanosleep.
(When logged in, completion status appears here.)