#include #include #include #include #include "mylock.h" #include "ordq.h" int ordq_init(ordq_t* q, ordq_data_killer_t killer, ordq_cmp_fn_t cmp) { if ((q == NULL) || (cmp == NULL)) { return -EINVAL; } mylock_init(&(q->lock)); q->head = NULL; q->killer = killer; q->cmp = cmp; q->ctx = NULL; return 0; } static int ordq_put_(ordq_t* q, ordq_item_t* it) { ordq_item_t** p = &(q->head); while ((*p) != NULL) { if (q->cmp(q->ctx, (*p)->data, it->data) > 0) { /* we found the location to insert */ break; } p = &((*p)->next); } it->next = *p; *p = it; return 0; } int ordq_put(ordq_t* q, void* data) { int rc = 0; ordq_item_t* it; it = (ordq_item_t*)calloc(1, sizeof(*it)); if (it == NULL) { return -ENOMEM; } it->data = data; mylock_lock(&(q->lock)); rc = ordq_put_(q, it); mylock_unlock(&(q->lock)); return rc; } void ordq_fini(ordq_t* q) { ordq_item_t* p = q->head; while (p != NULL) { ordq_item_t* p1 = p->next; if (q->killer != NULL) { q->killer(p->data); } p->data = NULL; free(p); p = p1; } mylock_fini(&(q->lock)); } static ordq_item_t* ordq_get_(ordq_t* q, ordq_match_fn_t matchfn, va_list ap) { ordq_item_t** p = NULL; ordq_item_t* it = NULL; p = &(q->head); while ((*p) != NULL) { va_list ap1; int rc = 0; if (matchfn == NULL) { break; } va_copy(ap1, ap); rc = matchfn((*p)->data, ap1); va_end(ap1); if (rc) { break; } p = &((*p)->next); } it = *p; if (it != NULL) { *p = it->next; it->next = NULL; } return it; } ordq_item_t* ordq_get(ordq_t* q, ordq_match_fn_t matchfn, ...) { ordq_item_t* it; va_list ap; va_start(ap, matchfn); mylock_lock(&(q->lock)); it = ordq_get_(q, matchfn, ap); mylock_unlock(&(q->lock)); va_end(ap); return it; } int ordq_del(ordq_t* q, ordq_match_fn_t matchfn, ...) { ordq_item_t* it = NULL; int count = 0; va_list ap, ap1; va_start(ap, matchfn); va_copy(ap1, ap); mylock_lock(&(q->lock)); while ((it = ordq_get_(q, matchfn, ap1)) != NULL) { if (q->killer != NULL) { q->killer(it->data); } free(it); count++; va_copy(ap1, ap); } mylock_unlock(&(q->lock)); va_end(ap1); va_end(ap); return count; } ordq_item_t* ordq_peek(ordq_t* q, ordq_match_fn_t matchfn, ...) { ordq_item_t* it = NULL; va_list ap; va_start(ap, matchfn); mylock_lock(&(q->lock)); it = q->head; while (it != NULL) { int rc = 0; va_list ap1; if (matchfn == NULL) { break; } va_copy(ap1, ap); rc = matchfn(it->data, ap1); va_end(ap1); if (rc) { break; } it = it->next; } mylock_unlock(&(q->lock)); va_end(ap); return it; } void ordq_set_ctx(ordq_t* q, void* ctx) { if (q == NULL) { return; } mylock_lock(&(q->lock)); q->ctx = ctx; mylock_unlock(&(q->lock)); }