#include #include "dataq.h" int dataq_init(dataq_t* q, data_item_killer_t killer) { q->head = q->tail = NULL; q->killer = killer; mylock_init(&(q->lock)); return 0; } static data_item_t* dataq_deq_head(dataq_t* q) { if (q->head != NULL) { data_item_t* b = NULL; b = q->head; q->head = b->next; b->next = NULL; if (q->head == NULL) { q->tail = NULL; } return b; } return NULL; } static data_item_t* dataq_deq_first_match(dataq_t* q, data_item_match_fn_t f) { data_item_t* prev = NULL; data_item_t* curr = q->head; while (curr != NULL) { if ((*f)(curr)) { // Found the item to remove if (prev == NULL) { // Removing the head item q->head = curr->next; if (q->head == NULL) { // Queue became empty after removing head q->tail = NULL; } // else: tail remains unchanged (it wasn't the head) } else { // Removing an item after prev (middle or tail) prev->next = curr->next; if (curr == q->tail) { // Check if we are removing the tail // We removed the tail item, prev is the new tail q->tail = prev; } // else: tail remains unchanged (it was further down the list) } curr->next = NULL; // Isolate the removed item return curr; // Return the removed item } // Move to the next item prev = curr; curr = curr->next; } return NULL; } data_item_t* dataq_deq(dataq_t* q, data_item_match_fn_t f) { data_item_t* b = NULL; mylock_lock(&(q->lock)); if (f == NULL) { b = dataq_deq_head(q); } else { b = dataq_deq_first_match(q, f); } mylock_unlock(&(q->lock)); return b; } int dataq_enq(dataq_t* q, data_item_t* b) { int rc = 0; b->next = NULL; mylock_lock(&(q->lock)); if (q->tail != NULL) { q->tail->next = b; } if (q->head == NULL) { q->head = b; } q->tail = b; mylock_unlock(&(q->lock)); return rc; } void dataq_fini(dataq_t* q) { data_item_t* it; while ((it = dataq_deq_head(q)) != NULL) { if (q->killer != NULL) { (q->killer)(it); } // Note: dataq_deq_head already isolates 'it' (it->next = NULL) } q->head = q->tail = NULL; // Explicitly set just in case. q->killer = NULL; return; }