I am trying to implement a queue in C that causes a process to non-busy wait until there is an element in the queue to consume. I have tried two different things to try to achieve this.
The first problem I have is if the enqueue/dequeue operations have if conditionals to check the bounds( if(q->count == QUEUESIZE) ), the call to sem_wait will return immediately because no other process has obtained a lock.
If I change the conditional to while(q->count == QUEUESIZE), I believe the consumer process will 'busy wait' until the semaphore is posted by the producer process, which is not my goal of the implementation, and through testing, I've found that the consumer process will not acquire the lock and continue.
I think that I am close, but I can't seem to figure out how to work around these issues. I have thought about adding condition variables or pthread_mutex, but wanted to exhaust the semaphore options before adding in additional complexity.
#define QUEUESIZE 48
typedef struct
{
char q[QUEUESIZE+1][150];
int first;
int last;
int count;
sem_t *lock;
} Queue;
init_queue(Queue *q, sem_t *l)
{
q->first = 0;
q->last = QUEUESIZE-1;
q->count = 0;
q->lock = l;
}
enqueue(Queue *q, char x[150])
{
while(q->count == QUEUESIZE)
sem_wait(q->lock);
if (q->count == 0)
{
if (sem_post(q->lock) == -1)
{
printf("Thread failed to unlock semaphore\n");
}
}
q->last = (q->last+1) % QUEUESIZE;
strcpy(q->q[ q->last ],x);
q->count = q->count + 1;
}
dequeue(Queue *q,char *ptr)
{
char x[150];
while(q->count == 0)
sem_wait(q->lock);
if (q->count == QUEUESIZE)
{
if (sem_post(q->lock) == -1)
{
printf("Thread failed to unlock semaphore\n");
}
}
strcpy(ptr,q->q[ q->first]);
q->first = (q->first+1) % QUEUESIZE;
q->count = q->count - 1;
}