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!!!

  1. 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.

  2. 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.

  3. 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