Split waitqueue from utils
parent
463d1c6435
commit
fae25515fa
|
@ -21,12 +21,13 @@
|
|||
} while (0)
|
||||
|
||||
#include <lighttpd/typedefs.h>
|
||||
#include <lighttpd/utils.h>
|
||||
#include <lighttpd/module.h>
|
||||
|
||||
#include <lighttpd/chunk.h>
|
||||
#include <lighttpd/chunk_parser.h>
|
||||
|
||||
#include <lighttpd/waitqueue.h>
|
||||
|
||||
#include <lighttpd/server.h>
|
||||
#include <lighttpd/worker.h>
|
||||
#include <lighttpd/condition.h>
|
||||
|
|
|
@ -13,23 +13,6 @@ typedef enum {
|
|||
} counter_type;
|
||||
|
||||
|
||||
struct waitqueue_elem {
|
||||
gboolean queued;
|
||||
ev_tstamp ts;
|
||||
waitqueue_elem *prev;
|
||||
waitqueue_elem *next;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
struct waitqueue {
|
||||
waitqueue_elem *head;
|
||||
waitqueue_elem *tail;
|
||||
ev_timer timer;
|
||||
struct ev_loop *loop;
|
||||
gdouble delay;
|
||||
};
|
||||
|
||||
|
||||
|
||||
LI_API void fatal(const gchar* msg);
|
||||
|
||||
|
@ -70,24 +53,4 @@ LI_API GString *mimetype_get(vrequest *vr, GString *filename);
|
|||
/* converts a sock_addr to a human readable string. ipv4 and ipv6 supported. if dest is NULL, a new string will be allocated */
|
||||
LI_API GString *sockaddr_to_string(sock_addr *saddr, GString *dest);
|
||||
|
||||
|
||||
/*
|
||||
* waitqueues are queues used to implement delays for certain tasks in a lightweight, non-blocking way
|
||||
* they are used for io timeouts or throttling for example
|
||||
* waitqueue_push, waitqueue_pop and waitqueue_remove have O(1) complexity
|
||||
*/
|
||||
|
||||
/* initializes a waitqueue by creating and starting the ev_timer. precision is sub-seconds */
|
||||
LI_API void waitqueue_init(waitqueue *queue, struct ev_loop *loop, waitqueue_cb callback, gdouble delay, gpointer data);
|
||||
/* stops the waitqueue. to restart it, simply call waitqueue_update */
|
||||
LI_API void waitqueue_stop(waitqueue *queue);
|
||||
/* updates the timeout of the waitqueue, you should allways call this at the end of your callback */
|
||||
LI_API void waitqueue_update(waitqueue *queue);
|
||||
/* moves the element to the end of the queue if already queued, appends it to the end otherwise */
|
||||
LI_API void waitqueue_push(waitqueue *queue, waitqueue_elem *elem);
|
||||
/* pops the first ready! element from the queue or NULL if none ready yet. this should be called in your callback */
|
||||
LI_API waitqueue_elem *waitqueue_pop(waitqueue *queue);
|
||||
/* removes an element from the queue */
|
||||
LI_API void waitqueue_remove(waitqueue *queue, waitqueue_elem *elem);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef _LIGHTTPD_WAITQUEUE_H_
|
||||
#define _LIGHTTPD_WAITQUEUE_H_
|
||||
|
||||
#ifndef _LIGHTTPD_BASE_H_
|
||||
#error Please include <lighttpd/base.h> instead of this file
|
||||
#endif
|
||||
|
||||
struct waitqueue_elem {
|
||||
gboolean queued;
|
||||
ev_tstamp ts;
|
||||
waitqueue_elem *prev;
|
||||
waitqueue_elem *next;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
struct waitqueue {
|
||||
waitqueue_elem *head;
|
||||
waitqueue_elem *tail;
|
||||
ev_timer timer;
|
||||
struct ev_loop *loop;
|
||||
gdouble delay;
|
||||
};
|
||||
|
||||
/*
|
||||
* waitqueues are queues used to implement delays for certain tasks in a lightweight, non-blocking way
|
||||
* they are used for io timeouts or throttling for example
|
||||
* waitqueue_push, waitqueue_pop and waitqueue_remove have O(1) complexity
|
||||
*/
|
||||
|
||||
/* initializes a waitqueue by creating and starting the ev_timer. precision is sub-seconds */
|
||||
LI_API void waitqueue_init(waitqueue *queue, struct ev_loop *loop, waitqueue_cb callback, gdouble delay, gpointer data);
|
||||
/* stops the waitqueue. to restart it, simply call waitqueue_update */
|
||||
LI_API void waitqueue_stop(waitqueue *queue);
|
||||
/* updates the timeout of the waitqueue, you should allways call this at the end of your callback */
|
||||
LI_API void waitqueue_update(waitqueue *queue);
|
||||
/* moves the element to the end of the queue if already queued, appends it to the end otherwise */
|
||||
LI_API void waitqueue_push(waitqueue *queue, waitqueue_elem *elem);
|
||||
/* pops the first ready! element from the queue or NULL if none ready yet. this should be called in your callback */
|
||||
LI_API waitqueue_elem *waitqueue_pop(waitqueue *queue);
|
||||
/* removes an element from the queue */
|
||||
LI_API void waitqueue_remove(waitqueue *queue, waitqueue_elem *elem);
|
||||
|
||||
#endif
|
|
@ -291,6 +291,7 @@ SET(COMMON_SRC
|
|||
utils.c
|
||||
value.c
|
||||
virtualrequest.c
|
||||
waitqueue.c
|
||||
worker.c
|
||||
|
||||
plugin_core.c
|
||||
|
|
102
src/utils.c
102
src/utils.c
|
@ -510,105 +510,3 @@ GString *sockaddr_to_string(sock_addr *saddr, GString *dest) {
|
|||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
void waitqueue_init(waitqueue *queue, struct ev_loop *loop, waitqueue_cb callback, gdouble delay, gpointer data) {
|
||||
ev_timer_init(&queue->timer, callback, delay, delay);
|
||||
ev_timer_start(loop, &queue->timer);
|
||||
|
||||
queue->timer.data = data;
|
||||
queue->head = queue->tail = NULL;
|
||||
queue->loop = loop;
|
||||
queue->delay = delay;
|
||||
}
|
||||
|
||||
void waitqueue_stop(waitqueue *queue) {
|
||||
ev_timer_stop(queue->loop, &queue->timer);
|
||||
}
|
||||
|
||||
void waitqueue_update(waitqueue *queue) {
|
||||
ev_tstamp repeat;
|
||||
|
||||
if (queue->head) {
|
||||
repeat = queue->head->ts + queue->delay - ev_now(queue->loop);
|
||||
} else
|
||||
repeat = queue->delay;
|
||||
|
||||
if (queue->timer.repeat != repeat)
|
||||
{
|
||||
queue->timer.repeat = repeat;
|
||||
ev_timer_again(queue->loop, &queue->timer);
|
||||
}
|
||||
}
|
||||
|
||||
void waitqueue_push(waitqueue *queue, waitqueue_elem *elem) {
|
||||
elem->ts = ev_now(queue->loop);
|
||||
|
||||
if (!elem->queued) {
|
||||
elem->queued = TRUE;
|
||||
/* not in the queue yet, insert at the end */
|
||||
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;
|
||||
if (elem->next)
|
||||
elem->next->prev = NULL;
|
||||
}
|
||||
|
||||
elem->prev = queue->tail;
|
||||
elem->next = NULL;
|
||||
queue->tail->next = elem;
|
||||
queue->tail = elem;
|
||||
}
|
||||
}
|
||||
|
||||
waitqueue_elem *waitqueue_pop(waitqueue *queue) {
|
||||
waitqueue_elem *elem = queue->head;
|
||||
ev_tstamp now = ev_now(queue->loop);
|
||||
|
||||
if (!elem || (elem->ts + queue->delay) >= now) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (elem != queue->tail)
|
||||
elem->next->prev = NULL;
|
||||
|
||||
queue->head = elem->next;
|
||||
|
||||
elem->queued = FALSE;
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
void waitqueue_remove(waitqueue *queue, waitqueue_elem *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->queued = FALSE;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
|
||||
#include <lighttpd/base.h>
|
||||
|
||||
void waitqueue_init(waitqueue *queue, struct ev_loop *loop, waitqueue_cb callback, gdouble delay, gpointer data) {
|
||||
ev_timer_init(&queue->timer, callback, delay, delay);
|
||||
ev_timer_start(loop, &queue->timer);
|
||||
|
||||
queue->timer.data = data;
|
||||
queue->head = queue->tail = NULL;
|
||||
queue->loop = loop;
|
||||
queue->delay = delay;
|
||||
}
|
||||
|
||||
void waitqueue_stop(waitqueue *queue) {
|
||||
ev_timer_stop(queue->loop, &queue->timer);
|
||||
}
|
||||
|
||||
void waitqueue_update(waitqueue *queue) {
|
||||
ev_tstamp repeat;
|
||||
|
||||
if (queue->head) {
|
||||
repeat = queue->head->ts + queue->delay - ev_now(queue->loop);
|
||||
} else
|
||||
repeat = queue->delay;
|
||||
|
||||
if (queue->timer.repeat != repeat)
|
||||
{
|
||||
queue->timer.repeat = repeat;
|
||||
ev_timer_again(queue->loop, &queue->timer);
|
||||
}
|
||||
}
|
||||
|
||||
void waitqueue_push(waitqueue *queue, waitqueue_elem *elem) {
|
||||
elem->ts = ev_now(queue->loop);
|
||||
|
||||
if (!elem->queued) {
|
||||
elem->queued = TRUE;
|
||||
/* not in the queue yet, insert at the end */
|
||||
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;
|
||||
if (elem->next)
|
||||
elem->next->prev = NULL;
|
||||
}
|
||||
|
||||
elem->prev = queue->tail;
|
||||
elem->next = NULL;
|
||||
queue->tail->next = elem;
|
||||
queue->tail = elem;
|
||||
}
|
||||
}
|
||||
|
||||
waitqueue_elem *waitqueue_pop(waitqueue *queue) {
|
||||
waitqueue_elem *elem = queue->head;
|
||||
ev_tstamp now = ev_now(queue->loop);
|
||||
|
||||
if (!elem || (elem->ts + queue->delay) >= now) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (elem != queue->tail)
|
||||
elem->next->prev = NULL;
|
||||
|
||||
queue->head = elem->next;
|
||||
|
||||
elem->queued = FALSE;
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
void waitqueue_remove(waitqueue *queue, waitqueue_elem *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->queued = FALSE;
|
||||
}
|
|
@ -36,6 +36,7 @@ common_source='''
|
|||
utils.c
|
||||
value.c
|
||||
virtualrequest.c
|
||||
waitqueue.c
|
||||
worker.c
|
||||
|
||||
plugin_core.c
|
||||
|
|
Loading…
Reference in New Issue