199 lines
3.3 KiB
C
199 lines
3.3 KiB
C
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <strings.h>
|
|
|
|
#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));
|
|
}
|