16.2 Bounded Buffer Protected by Mutex LocksFigure 16.2 shows a diagram of a circular buffer with eight slots that might be used as a holding area between producers and consumers. The buffer has three data items, and the remaining five slots are free. The bufout variable has the slot number of the next data item to be removed, and the bufin variable has the number of the next slot to be filled. Figure 16.2. Circular buffer.![]() Appendix A.5 for a discussion of the two meanings of the static qualifier in C.) The code is in a separate file so that the program can access the buffer only through getitem and putitem. The header file, buffer.h, contains the definitions of BUFSIZE and buffer_t. The functions of Program 16.1 follow the preferred POSIX error-handling semantics and return 0 if successful or a nonzero error code if unsuccessful. Program 16.1 bufferbad.cA flawed circular buffer protected by mutex locks.
Exercise 16.1The following code segment uses the circular buffer defined in Program 16.1. What happens when it executes?
Answer:The result cannot be predicted. The getitem returns an error only when the locking fails, but it does not keep track of the number of items in the buffer. If a consumer executes this code before a producer calls putitem, the value retrieved for myitem will not be meaningful. Exercise 16.2The following code segment uses the circular buffer defined in Program 16.1. What happens when it executes?
Answer:The buffer has only 8 slots, but this code segment calls putitem 10 times. The putitem does not keep track of how many empty slots are available, so it does not report an error if full slots are overwritten. If a consumer does not call getitem, the code overwrites the first items in the buffer.Program 16.1 is flawed because the code does not protect the buffer from overflows or underflows. Program 16.2 is a revised implementation that keeps track of the number of items actually in the buffer. If successful, getitem and putitem return 0. If unsuccessful, these functions return a nonzero error code. In particular, getitem returns EAGAIN if the buffer is empty, and putitem returns EAGAIN if the buffer is full. Example 16.3The following code segment attempts to retrieve at most 10 items from the buffer of Program 16.2.
Program 16.2 buffer.cA circular buffer implementation that does not allow overwriting of full slots or retrieval of empty slots.
The while loop of Example 16.3 uses busy waiting. The implementation is worse than you might imagine. Not only does busy waiting waste CPU time, but consumers executing this code segment block the producers, resulting in even more delay. Depending on the thread-scheduling algorithm, a busy-waiting consumer could prevent a producer from ever obtaining the CPU. |