the upcoming 2.0 version
https://redmine.lighttpd.net/projects/lighttpd2
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
3.7 KiB
186 lines
3.7 KiB
|
|
#include <lighttpd/waitqueue.h> |
|
|
|
static void wq_cb(liEventBase *watcher, int events) { |
|
liWaitQueue *queue = LI_CONTAINER_OF(li_event_timer_from(watcher), liWaitQueue, timer); |
|
UNUSED(events); |
|
|
|
queue->callback(queue, queue->data); |
|
} |
|
|
|
void li_waitqueue_init(liWaitQueue *queue, liEventLoop *loop, liWaitQueueCB callback, gdouble delay, gpointer data) { |
|
li_event_timer_init(loop, &queue->timer, wq_cb); |
|
|
|
queue->head = queue->tail = NULL; |
|
queue->delay = delay; |
|
queue->callback = callback; |
|
queue->data = data; |
|
queue->length = 0; |
|
} |
|
|
|
void li_waitqueue_stop(liWaitQueue *queue) { |
|
li_event_clear(&queue->timer); |
|
} |
|
|
|
void li_waitqueue_set_delay(liWaitQueue *queue, gdouble delay) { |
|
queue->delay = delay; |
|
|
|
if (li_event_active(&queue->timer)) { |
|
li_waitqueue_update(queue); |
|
} |
|
} |
|
|
|
void li_waitqueue_update(liWaitQueue *queue) { |
|
li_tstamp repeat; |
|
li_tstamp now = li_event_now(li_event_get_loop(&queue->timer)); |
|
|
|
if (G_LIKELY(queue->head)) { |
|
repeat = queue->head->ts + queue->delay - now; |
|
|
|
if (repeat < 0.05) repeat = 0.05; |
|
|
|
li_event_timer_once(&queue->timer, repeat); |
|
} else { |
|
/* stop timer if queue empty */ |
|
li_event_stop(&queue->timer); |
|
return; |
|
} |
|
} |
|
|
|
void li_waitqueue_push(liWaitQueue *queue, liWaitQueueElem *elem) { |
|
elem->ts = li_event_now(li_event_get_loop(&queue->timer)); |
|
|
|
if (!elem->queued) { |
|
/* not in the queue yet, insert at the end */ |
|
elem->queued = TRUE; |
|
queue->length++; |
|
|
|
if (!queue->head) { |
|
/* queue is empty */ |
|
queue->head = elem; |
|
queue->tail = elem; |
|
elem->prev = NULL; |
|
elem->next = NULL; |
|
} else { |
|
/* queue not empty */ |
|
elem->prev = queue->tail; |
|
elem->next = NULL; |
|
queue->tail->next = elem; |
|
queue->tail = elem; |
|
} |
|
} else { |
|
/* already queued, move to end */ |
|
if (elem == queue->tail) |
|
return; |
|
|
|
if (elem == queue->head) |
|
queue->head = elem->next; |
|
else |
|
elem->prev->next = elem->next; |
|
|
|
elem->next->prev = elem->prev; |
|
elem->prev = queue->tail; |
|
elem->next = NULL; |
|
queue->tail->next = elem; |
|
queue->tail = elem; |
|
} |
|
|
|
if (G_UNLIKELY(!li_event_active(&queue->timer))) |
|
li_event_timer_once(&queue->timer, queue->delay); |
|
} |
|
|
|
liWaitQueueElem *li_waitqueue_pop(liWaitQueue *queue) { |
|
liWaitQueueElem *elem = queue->head; |
|
li_tstamp now = li_event_now(li_event_get_loop(&queue->timer)); |
|
|
|
if (!elem || (elem->ts + queue->delay) > now) { |
|
return NULL; |
|
} |
|
|
|
if (elem == queue->tail) |
|
queue->tail = NULL; |
|
else |
|
elem->next->prev = NULL; |
|
|
|
queue->head = elem->next; |
|
queue->length--; |
|
|
|
elem->ts = 0; |
|
elem->queued = FALSE; |
|
|
|
return elem; |
|
} |
|
|
|
liWaitQueueElem *li_waitqueue_pop_force(liWaitQueue *queue) { |
|
liWaitQueueElem *elem = queue->head; |
|
|
|
if (!elem) { |
|
return NULL; |
|
} |
|
|
|
if (elem == queue->tail) |
|
queue->tail = NULL; |
|
else |
|
elem->next->prev = NULL; |
|
|
|
queue->head = elem->next; |
|
queue->length--; |
|
|
|
elem->ts = 0; |
|
elem->queued = FALSE; |
|
|
|
return elem; |
|
} |
|
|
|
void li_waitqueue_remove(liWaitQueue *queue, liWaitQueueElem *elem) { |
|
if (!elem->queued) |
|
return; |
|
|
|
if (elem == queue->head) |
|
queue->head = elem->next; |
|
else |
|
elem->prev->next = elem->next; |
|
|
|
if (elem == queue->tail) |
|
queue->tail = elem->prev; |
|
else |
|
elem->next->prev = elem->prev; |
|
|
|
elem->ts = 0; |
|
elem->queued = FALSE; |
|
queue->length--; |
|
|
|
if (G_UNLIKELY(!queue->head)) |
|
li_event_stop(&queue->timer); |
|
} |
|
|
|
guint li_waitqueue_pop_ready(liWaitQueue *queue, liWaitQueueElem **head) { |
|
guint i = 0; |
|
liWaitQueueElem *elem = queue->head; |
|
li_tstamp now = li_event_now(li_event_get_loop(&queue->timer)); |
|
|
|
*head = elem; |
|
|
|
while (elem != NULL) { |
|
if ((elem->ts + queue->delay) > now) { |
|
queue->head = elem; |
|
|
|
if (elem->prev) { |
|
elem->prev->next = NULL; |
|
} |
|
|
|
return i; |
|
} |
|
|
|
elem->ts = 0; |
|
elem->queued = FALSE; |
|
elem = elem->next; |
|
queue->length--; |
|
i++; |
|
} |
|
|
|
queue->head = NULL; |
|
queue->tail = NULL; |
|
|
|
return i; |
|
}
|
|
|