myxce/src/lib/dataq.c

116 lines
2.6 KiB
C

#include <stdlib.h>
#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;
}