I'm assuming you have a threaded-like environment, with fork or pthread_create...
Your problem is also known as "the busy barber", or "the sleepy barber", a classical subject of computer sciences.
You need to use two semaphores to handle the critical region, one to avoid consumers of reading empty buffers and another one to stop producers to insert anything when the buffer's full.
This is a piece of a code I used in a c++ class used for synching multithreads... I just do not control whether the buffer's full or not, I simply don't mind (I just check the memory consumption, but buffer's level is always low in my program)
Code:
void Produce(Item *t) {
down_mutex(); // enter critical region
_buffer.put_buffer(t); // produce on your circular buffer
is_empty=false;
_count++; //any check for is_full would be done here!
up_mutex();
up_empty (); // release customers waiting when buffer's empty
}
and the consumer:
Item * Consume () {
Item * ret;
down_empty(); // go sleep if ain't no messages, up_empty releases!!
down_mutex(); // enter RC
ret = get_buffer(); // consume
if (--_count==0) is_empty=true; // down_empty controls
up_mutex();
return ret;
}
Now, just rewrite it using semaphores... follows the supressed functions.
Code:
void down_mutex() { pthread_mutex_lock(&mutex); }
void up_mutex() { pthread_mutex_unlock(&mutex); }
void down_empty() { while(is_empty) pthread_cond_wait(&empty, &mutex); up_mutex(); }
void up_empty() { pthread_cond_signal(&empty); }
void down_full() { while(is_full) pthread_cond_wait(&full, &mutex); up_mutex(); }
void up_full() { pthread_cond_signal(&full); }
Good luck!
yezaim