Add an async queueing mechanism
authorVolker Lendecke <vl@samba.org>
Sun, 4 Jan 2009 10:28:40 +0000 (11:28 +0100)
committerVolker Lendecke <vl@samba.org>
Sun, 4 Jan 2009 15:42:40 +0000 (16:42 +0100)
source3/include/async_req.h
source3/lib/async_req.c

index bbe52da723c5369697678ed09453195c40afd694..1b8dbf33468b0567a23651de2841c161df52e081 100644 (file)
@@ -141,5 +141,13 @@ struct async_req *async_wait_send(TALLOC_CTX *mem_ctx,
 
 NTSTATUS async_wait_recv(struct async_req *req);
 
+struct async_req_queue;
+
+struct async_req_queue *async_req_queue_init(TALLOC_CTX *mem_ctx);
+
+bool async_req_enqueue(struct async_req_queue *queue,
+                      struct event_context *ev,
+                      struct async_req *req,
+                      void (*trigger)(struct async_req *req));
 
 #endif
index 0653ff62a7fed1f15d8022110f49e399a12ca848..ac06df65a3ab92e400be12e3e4b425b7b8026a11 100644 (file)
@@ -236,3 +236,81 @@ NTSTATUS async_wait_recv(struct async_req *req)
 {
        return NT_STATUS_OK;
 }
+
+struct async_queue_entry {
+       struct async_queue_entry *prev, *next;
+       struct async_req_queue *queue;
+       struct async_req *req;
+       void (*trigger)(struct async_req *req);
+};
+
+struct async_req_queue {
+       struct async_queue_entry *queue;
+};
+
+struct async_req_queue *async_req_queue_init(TALLOC_CTX *mem_ctx)
+{
+       return TALLOC_ZERO_P(mem_ctx, struct async_req_queue);
+}
+
+static int async_queue_entry_destructor(struct async_queue_entry *e)
+{
+       struct async_req_queue *queue = e->queue;
+
+       DLIST_REMOVE(queue->queue, e);
+
+       if (queue->queue != NULL) {
+               queue->queue->trigger(queue->queue->req);
+       }
+
+       return 0;
+}
+
+static void async_req_immediate_trigger(struct event_context *ev,
+                                       struct timed_event *te,
+                                       const struct timeval *now,
+                                       void *priv)
+{
+       struct async_queue_entry *e = talloc_get_type_abort(
+               priv, struct async_queue_entry);
+
+       TALLOC_FREE(te);
+       e->trigger(e->req);
+}
+
+bool async_req_enqueue(struct async_req_queue *queue, struct event_context *ev,
+                      struct async_req *req,
+                      void (*trigger)(struct async_req *req))
+{
+       struct async_queue_entry *e;
+       bool busy;
+
+       busy = (queue->queue != NULL);
+
+       e = talloc(req, struct async_queue_entry);
+       if (e == NULL) {
+               return false;
+       }
+
+       e->req = req;
+       e->trigger = trigger;
+       e->queue = queue;
+
+       DLIST_ADD_END(queue->queue, e, struct async_queue_entry *);
+       talloc_set_destructor(e, async_queue_entry_destructor);
+
+       if (!busy) {
+               struct timed_event *te;
+
+               te = event_add_timed(ev, e, timeval_zero(),
+                                    "async_req_immediate_trigger",
+                                    async_req_immediate_trigger,
+                                    e);
+               if (te == NULL) {
+                       TALLOC_FREE(e);
+                       return false;
+               }
+       }
+
+       return true;
+}