diff options
-rw-r--r-- | lib/tevent/libtevent.m4 | 2 | ||||
-rw-r--r-- | lib/tevent/tevent.h | 22 | ||||
-rw-r--r-- | lib/tevent/tevent_queue.c | 198 |
3 files changed, 221 insertions, 1 deletions
diff --git a/lib/tevent/libtevent.m4 b/lib/tevent/libtevent.m4 index 29a64ae3b3..c316823a71 100644 --- a/lib/tevent/libtevent.m4 +++ b/lib/tevent/libtevent.m4 @@ -27,7 +27,7 @@ AC_SUBST(TEVENT_LIBS) TEVENT_CFLAGS="-I$teventdir" TEVENT_OBJ="tevent.o tevent_fd.o tevent_timed.o tevent_signal.o tevent_debug.o tevent_util.o" -TEVENT_OBJ="$TEVENT_OBJ tevent_req.o tevent_wakeup.o" +TEVENT_OBJ="$TEVENT_OBJ tevent_req.o tevent_wakeup.o tevent_queue.o" TEVENT_OBJ="$TEVENT_OBJ tevent_standard.o tevent_select.o" AC_CHECK_HEADERS(sys/epoll.h) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 185a8fa193..8c119ffb8e 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -338,6 +338,28 @@ struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs, struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs); +struct tevent_queue; + +struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, + const char *name, + const char *location); + +#define tevent_queue_create(_mem_ctx, _name) \ + _tevent_queue_create((_mem_ctx), (_name), __location__) + +typedef void (*tevent_queue_trigger_fn_t)(struct tevent_req *req, + void *private_data); +bool tevent_queue_add(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data); +bool tevent_queue_start(struct tevent_queue *queue, + struct tevent_context *ev); +void tevent_queue_stop(struct tevent_queue *queue); + +size_t tevent_queue_length(struct tevent_queue *queue); + #ifdef TEVENT_COMPAT_DEFINES #define event_context tevent_context diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c new file mode 100644 index 0000000000..6c8fbe4f95 --- /dev/null +++ b/lib/tevent/tevent_queue.c @@ -0,0 +1,198 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async requests + Copyright (C) Volker Lendecke 2008 + Copyright (C) Stefan Metzmacher 2009 + + ** NOTE! The following LGPL license applies to the tevent + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +struct tevent_queue_entry { + struct tevent_queue_entry *prev, *next; + struct tevent_queue *queue; + + bool triggered; + + struct tevent_req *req; + + tevent_queue_trigger_fn_t trigger; + void *private_data; +}; + +struct tevent_queue { + const char *name; + const char *location; + + bool running; + struct tevent_timer *timer; + + size_t length; + struct tevent_queue_entry *list; +}; + +static int tevent_queue_entry_destructor(struct tevent_queue_entry *e) +{ + struct tevent_queue *q = e->queue; + + if (!q) { + return 0; + } + + DLIST_REMOVE(q->list, e); + q->length--; + + if (e->triggered && + q->running && + q->list) { + q->list->triggered = true; + q->list->trigger(q->list->req, + q->list->private_data); + } + + return 0; +} + +static int tevent_queue_destructor(struct tevent_queue *q) +{ + q->running = false; + + while (q->list) { + struct tevent_queue_entry *e = q->list; + talloc_free(e); + } + + return 0; +} + +struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, + const char *name, + const char *location) +{ + struct tevent_queue *queue; + + queue = talloc_zero(mem_ctx, struct tevent_queue); + if (!queue) { + return NULL; + } + + queue->name = talloc_strdup(queue, name); + if (!queue->name) { + talloc_free(queue); + return NULL; + } + + queue->location = location; + + /* queue is running by default */ + queue->running = true; + + talloc_set_destructor(queue, tevent_queue_destructor); + return queue; +} + +static void tevent_queue_timer_start(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval now, + void *private_data) +{ + struct tevent_queue *q = talloc_get_type(private_data, + struct tevent_queue); + + talloc_free(te); + q->timer = NULL; + + q->list->triggered = true; + q->list->trigger(q->list->req, q->list->private_data); +} + +bool tevent_queue_add(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +{ + struct tevent_queue_entry *e; + + e = talloc_zero(req, struct tevent_queue_entry); + if (e == NULL) { + return false; + } + + e->queue = queue; + e->req = req; + e->trigger = trigger; + e->private_data = private_data; + + if (queue->running && + !queue->timer && + !queue->list) { + queue->timer = tevent_add_timer(ev, queue, tevent_timeval_zero(), + tevent_queue_timer_start, + queue); + if (!queue->timer) { + talloc_free(e); + return false; + } + } + + DLIST_ADD_END(queue->list, e, struct tevent_queue_entry *); + queue->length++; + talloc_set_destructor(e, tevent_queue_entry_destructor); + + return true; +} + +bool tevent_queue_start(struct tevent_queue *queue, + struct tevent_context *ev) +{ + if (queue->running) { + /* already started */ + return true; + } + + if (!queue->timer && + queue->list) { + queue->timer = tevent_add_timer(ev, queue, tevent_timeval_zero(), + tevent_queue_timer_start, + queue); + if (!queue->timer) { + return false; + } + } + + queue->running = true; + + return true; +} + +void tevent_queue_stop(struct tevent_queue *queue) +{ + queue->running = false; + talloc_free(queue->timer); + queue->timer = NULL; +} + +size_t tevent_queue_length(struct tevent_queue *queue) +{ + return queue->length; +} |