2 * Facility for queueing callback functions to be run from the
3 * top-level event loop after the current top-level activity finishes.
11 struct callback
*next
;
13 toplevel_callback_fn_t fn
;
17 static struct callback
*cbcurr
= NULL
, *cbhead
= NULL
, *cbtail
= NULL
;
19 static toplevel_callback_notify_fn_t notify_frontend
= NULL
;
20 static void *notify_ctx
= NULL
;
22 void request_callback_notifications(toplevel_callback_notify_fn_t fn
,
29 static void run_idempotent_callback(void *ctx
)
31 struct IdempotentCallback
*ic
= (struct IdempotentCallback
*)ctx
;
36 void queue_idempotent_callback(struct IdempotentCallback
*ic
)
41 queue_toplevel_callback(run_idempotent_callback
, ic
);
44 void delete_callbacks_for_context(void *ctx
)
46 struct callback
*newhead
, *newtail
;
48 newhead
= newtail
= NULL
;
50 struct callback
*cb
= cbhead
;
51 cbhead
= cbhead
->next
;
53 (cb
->fn
== run_idempotent_callback
&&
54 ((struct IdempotentCallback
*)cb
->ctx
)->ctx
== ctx
)) {
72 void queue_toplevel_callback(toplevel_callback_fn_t fn
, void *ctx
)
76 cb
= snew(struct callback
);
81 * If the front end has requested notification of pending
82 * callbacks, and we didn't already have one queued, let it know
85 * If cbcurr is non-NULL, i.e. we are actually in the middle of
86 * executing a callback right now, then we count that as the queue
87 * already having been non-empty. That saves the front end getting
88 * a constant stream of needless re-notifications if the last
89 * callback keeps re-scheduling itself.
91 if (notify_frontend
&& !cbhead
&& !cbcurr
)
92 notify_frontend(notify_ctx
);
102 bool run_toplevel_callbacks(void)
104 bool done_something
= false;
108 * Transfer the head callback into cbcurr to indicate that
109 * it's being executed. Then operations which transform the
110 * queue, like delete_callbacks_for_context, can proceed as if
114 cbhead
= cbhead
->next
;
119 * Now run the callback, and then clear it out of cbcurr.
121 cbcurr
->fn(cbcurr
->ctx
);
125 done_something
= true;
127 return done_something
;
130 bool toplevel_callback_pending(void)
132 return cbcurr
!= NULL
|| cbhead
!= NULL
;