116 lines
2.6 KiB
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;
|
|
}
|