I am currently working on a queue structure which is tread-safe. I lock before editing queue in push and pop. Unlock it when I finish doing that. Now I want to let thread wait when pop-empty-queue or push-full-queue(this queue is sized). So I check if queue is full at the beginning of push, and use same way to check if queue is empty the beginning of pop. If it is then I let it wait by pthread_cond_wait
. To let it stop waiting, I check if queue is still empty at the end of push, and check if queue is still full at the end of pop. Is it's not empty or full, then I use pthread_cond_signal
to wake up the thread. The struct that I defined is like
typedef struct node_t {
void* content;
struct node_t *next;
struct node_t *prev;
} node_t;
typedef struct queue_t {
node_t* head;
node_t* tail;
int size;
int count;
pthread_mutex_t mutex;
pthread_cond_t full; // To deal with the condition that the queue is full
pthread_cond_t empty; // To deal with the condition that the queue is empty
} queue_t;
And the way I use lock and wait & send code is like:
bool queue_push(queue_t *q, void *elem) {
if (q == NULL) {
return false;
}
while (q->count == q->size) {
pthread_cond_wait(&q->full, &q->mutex);
}
if (q->head == NULL) {
pthread_mutex_lock(&q->mutex);
// I skip the steps for adding a node to queue
if (q->count != 0) {
pthread_cond_signal(&q->empty);
}
pthread_mutex_unlock(&q->mutex);
return true;
} else {
pthread_mutex_lock(&q->mutex);
// I skip the steps for adding a node to queue
if (q->count != 0) {
pthread_cond_signal(&q->empty);
}
pthread_mutex_unlock(&q->mutex);
return true;
}
}
And the code for pop is kind of similar.
bool queue_pop(queue_t *q, void **elem) {
if (q->count == 0) {
pthread_cond_wait(&q->empty, &q->mutex);
}
if (q->head == q->tail) {
pthread_mutex_lock(&q->mutex);
// I skip the steps for deleting a node to queue
if (q->count != q->size) {
pthread_cond_signal(&q->full);
}
pthread_mutex_unlock(&q->mutex);
return true;
} else {
pthread_mutex_lock(&q->mutex);
// I skip the steps for deleting a node to queue
if (q->count != q->size) {
pthread_cond_signal(&q->full);
}
pthread_mutex_unlock(&q->mutex);
return true;
}
}
Now when I use my test cases to test it, it never end. But I did unlock and send signal to let thread stop waiting. Can someone help me about this? Thanks!