Mike's Guide to a Ring Buffer Lab
Forget Google to begin with!!!
Try to break the lab down into 'easy' problems.
To me
there are 3 major objects/functions that need
to be created and made to work together.
The list is ordered because, you really need to attack
things in order!!!
-
Ring Buffer
The ring buffer is a data structure that holds data that is transferred
between the Producer and the Consumer.
The ring buffer is a 'shared' medium that has only 'one' copy.
The approach in the lecture notes was to use
a
static
struct.
This means there is only copy that comes into existence at the start
of execution.
This copy is shared by all the routines.
The other aspect of the ring buffer is the fact that there are two
indexes.
The
input
index points to the next cell to be filled;
The
output
index points to the next cell to be emptied.
Using modulo arithmetic, you need to keep track of these pointers.
You also need to know when the ring buffer is empty or full.
The lab description gives a good start on the ring buffer,
and the lecture notes cover the modulo issues.
-
Producer
The Producer is a function that reads from the input file and stores
data in the ring buffer.
A good way to build the ring buffer lab is to
first write a Producer like function that reads
the input file and fills in the ring buffer.
You might have this function loop reading input, loading the
next ring
buffer position, and printing the whole ring buffer out. You
could stop at full or you could go past full, testing the modulo
arithmetic applied to the index.
Once you have this function, you know that the ring buffer works
and that you can load and print the buffer.
Exactly how to read the last input message is tricky.
You should think about how this needs to work before worrying
about threads.
-
Consumer
The Consumer is a function that reads each entry in the ring buffer
and prints out the value.
Creating this function after the Producer, lets you test your ability
to access the ring buffer.
To test the Consumer, you could run the Producer for X entries, and
then call the Consumer.
Given that from the above steps
you have built a static ring buffer, a Producer that fills the
ring buffer, and a Consumer that empties the ring buffer,
the movement to threads is the next step (really not that difficult).
Besides creating threads, you need to understand functions that
provide mutual exclusion to the ring buffer, that wait for ring
buffer conditions (an empty position, a full position, etc.).
The key is to read the man pages and/or Google.
Thread creation is straight forward. What is not is condition
variables and checking for them.
I find that there are a couple of details of the condition
operations that bother me, so read carefully.
Make sure you understand that a mutex needs to be set before
checking for a condition.
The Sleep function is another area of concern.
The lab writeup gives some details, but we have seen various
issues.
First, your function should allocate a local copy of the appropriate
structure, then pass a pointer to that structure when calling
nanosleep.
Second, you do not need a malloc for the timespec structure.
Just allocate a local copy.
Mike Erlinger
Last Modified Thursday, 30-Jun-2011 12:44:12 PDT