summaryrefslogtreecommitdiffstats
path: root/ctdb/lib/tevent/tevent_queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'ctdb/lib/tevent/tevent_queue.c')
-rw-r--r--ctdb/lib/tevent/tevent_queue.c99
1 files changed, 91 insertions, 8 deletions
diff --git a/ctdb/lib/tevent/tevent_queue.c b/ctdb/lib/tevent/tevent_queue.c
index 3715c35e4f..4750675802 100644
--- a/ctdb/lib/tevent/tevent_queue.c
+++ b/ctdb/lib/tevent/tevent_queue.c
@@ -144,17 +144,19 @@ static void tevent_queue_immediate_trigger(struct tevent_context *ev,
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)
+static struct tevent_queue_entry *tevent_queue_add_internal(
+ struct tevent_queue *queue,
+ struct tevent_context *ev,
+ struct tevent_req *req,
+ tevent_queue_trigger_fn_t trigger,
+ void *private_data,
+ bool allow_direct)
{
struct tevent_queue_entry *e;
e = talloc_zero(req, struct tevent_queue_entry);
if (e == NULL) {
- return false;
+ return NULL;
}
e->queue = queue;
@@ -163,16 +165,53 @@ bool tevent_queue_add(struct tevent_queue *queue,
e->trigger = trigger;
e->private_data = private_data;
+ /*
+ * if there is no trigger, it is just a blocker
+ */
+ if (trigger == NULL) {
+ e->triggered = true;
+ }
+
+ if (queue->length > 0) {
+ /*
+ * if there are already entries in the
+ * queue do not optimize.
+ */
+ allow_direct = false;
+ }
+
+ if (req->async.fn != NULL) {
+ /*
+ * If the callers wants to optimize for the
+ * empty queue case, call the trigger only
+ * if there is no callback defined for the
+ * request yet.
+ */
+ allow_direct = false;
+ }
+
DLIST_ADD_END(queue->list, e, struct tevent_queue_entry *);
queue->length++;
talloc_set_destructor(e, tevent_queue_entry_destructor);
if (!queue->running) {
- return true;
+ return e;
}
if (queue->list->triggered) {
- return true;
+ return e;
+ }
+
+ /*
+ * If allowed we directly call the trigger
+ * avoiding possible delays caused by
+ * an immediate event.
+ */
+ if (allow_direct) {
+ queue->list->triggered = true;
+ queue->list->trigger(queue->list->req,
+ queue->list->private_data);
+ return e;
}
tevent_schedule_immediate(queue->immediate,
@@ -180,9 +219,48 @@ bool tevent_queue_add(struct tevent_queue *queue,
tevent_queue_immediate_trigger,
queue);
+ return e;
+}
+
+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 = tevent_queue_add_internal(queue, ev, req,
+ trigger, private_data, false);
+ if (e == NULL) {
+ return false;
+ }
+
return true;
}
+struct tevent_queue_entry *tevent_queue_add_entry(
+ struct tevent_queue *queue,
+ struct tevent_context *ev,
+ struct tevent_req *req,
+ tevent_queue_trigger_fn_t trigger,
+ void *private_data)
+{
+ return tevent_queue_add_internal(queue, ev, req,
+ trigger, private_data, false);
+}
+
+struct tevent_queue_entry *tevent_queue_add_optimize_empty(
+ struct tevent_queue *queue,
+ struct tevent_context *ev,
+ struct tevent_req *req,
+ tevent_queue_trigger_fn_t trigger,
+ void *private_data)
+{
+ return tevent_queue_add_internal(queue, ev, req,
+ trigger, private_data, true);
+}
+
void tevent_queue_start(struct tevent_queue *queue)
{
if (queue->running) {
@@ -215,3 +293,8 @@ size_t tevent_queue_length(struct tevent_queue *queue)
{
return queue->length;
}
+
+bool tevent_queue_running(struct tevent_queue *queue)
+{
+ return queue->running;
+}