Circular Buffer Problem

A classic problem in operating system is to handle the producer and consumer scenario. Producer will keep producing new data and consumer will consume that data. To do so say the producer and consumer process share the same memory. Lets say the size of that memory shared is fixed or bounded. Can you implement a logic to produce a data to that buffer when space is available. Similarly consumer can read only when data is available and the buffer is not empty.

This can be achieved by a circular bounded buffer shared between the producer and consumer.

/* the size of the bounded shared buffer */
#define BUFFER_SIZE 10


/* Each elements of the buffer */
typedef struct element {
	int i;//some data is present
}element;


/* The shared buffer, each index is of the type element */
element data_buffer[BUFFER_SIZE];

Let us come with the logic

Other than sharing the data_buffer, the producer and consumer must share the index where to produce data and from where to consume it.

Let’s define that

/* Add element in position "in" and move to next */
int in = 0; 

/* remove element from position "out" and move to next */
int out = 0;

Now how to know when the buffer is FULL so any element can’t be added. Similarly how to know when buffer is empty when element can be read or consumed. Let’s define the rules

/* if in == out, buffer is empty */

/* if (in + 1)%BUFFER_SIZE == out buffer is full */

Okay now lets write the pseudo code of the producer

/* producer */

while(TRUE) {

        /* keep waiting as buffer is full*/
	while((in + 1)%BUFFER_SIZE == out);
 
	data_buffer[in] = data_produced;
	in = (in+1)%BUFFER_SIZE;

}

The consumer pseudo code

/* consumer */

while(TRUE) {

        /* keep waiting as buffer is empty, nothing to consume */
	while(in == out);
	
	data_consumed = data_buffer[out];
	out = (out + 1)%BUFFER_SIZE;

}

I hope the above logic is self explanatory. I have a question for you, how many elements will make the buffer full in the above logic ?