#include <pzk_dequeue.h>
static pzk_dequeue_node_t* _new_pzk_dequeue_node(void* val) {
pzk_dequeue_node_t* node = (pzk_dequeue_node_t*) calloc(1, sizeof(pzk_dequeue_node_t));
node->value = val;
return node;
}
static void _destroy_pzk_dequeue_node(pzk_dequeue_node_t* node) {
if (node) free(node);
}
static int pzk_dequeue_push(pzk_dequeue_t* dq, void* val) {
pthread_mutex_lock(dq->mutex);
pzk_dequeue_node_t* new = _new_pzk_dequeue_node(val);
pzk_dequeue_node_t* last = dq->last;
if (last) {
last->next = new;
new->prev = last;
dq->last = new;
} else {
dq->first = dq->last = new;
}
dq->size++;
pthread_mutex_unlock(dq->mutex);
return 0;
}
static int pzk_dequeue_unshift(pzk_dequeue_t* dq, void* val) {
pthread_mutex_lock(dq->mutex);
pzk_dequeue_node_t* new = _new_pzk_dequeue_node(val);
pzk_dequeue_node_t* first = dq->first;
if (first) {
first->prev = new;
new->next = first;
dq->first = new;
} else {
dq->first = dq->last = new;
}
dq->size++;
pthread_mutex_unlock(dq->mutex);
return 0;
}
static void* pzk_dequeue_pop(pzk_dequeue_t* dq) {
pthread_mutex_lock(dq->mutex);
pzk_dequeue_node_t* node;
pzk_dequeue_node_t* last = dq->last;
if (!last) {
pthread_mutex_unlock(dq->mutex);
return NULL;
}
pzk_dequeue_node_t* prev = last->prev;
if (prev) {
prev->next = NULL;
dq->last = prev;
} else {
dq->first = dq->last = NULL;
}
void* value = last->value;
_destroy_pzk_dequeue_node(last);
dq->size--;
pthread_mutex_unlock(dq->mutex);
return value;
}
static void* pzk_dequeue_shift(pzk_dequeue_t* dq) {
pthread_mutex_lock(dq->mutex);
pzk_dequeue_node_t* node;
pzk_dequeue_node_t* first = dq->first;
if (!first) {
pthread_mutex_unlock(dq->mutex);
return NULL;
}
pzk_dequeue_node_t* next = first->next;
if (next) {
next->prev = NULL;
dq->first = next;
} else {
dq->first = dq->last = NULL;
}
void* value = first->value;
_destroy_pzk_dequeue_node(first);
dq->size--;
pthread_mutex_unlock(dq->mutex);
return value;
}
static void destroy_pzk_dequeue(pzk_dequeue_t* dq) {
size_t size = dq->size;
pzk_dequeue_node_t* node;
if (size) {
int i;
for (i = 0, node = dq->first; i < size; i++) {
pzk_dequeue_node_t* next = node->next;
_destroy_pzk_dequeue_node(node);
node = next;
}
}
if (dq->mutex) {
pthread_mutex_destroy(dq->mutex);
free(dq->mutex);
}
free(dq);
}
pzk_dequeue_t* new_pzk_dequeue() {
pzk_dequeue_t* dq = (pzk_dequeue_t*) calloc(1, sizeof(pzk_dequeue_t));
dq->mutex = (pthread_mutex_t*) calloc(1, sizeof(pthread_mutex_t));
pthread_mutex_init(dq->mutex, NULL);
dq->push = pzk_dequeue_push;
dq->pop = pzk_dequeue_pop;
dq->unshift = pzk_dequeue_unshift;
dq->shift = pzk_dequeue_shift;
dq->destroy = destroy_pzk_dequeue;
return dq;
}