diff options
author | Kaim, Sean M <Sean.Kaim@ca.com> | 2015-11-04 23:46:18 +0300 |
---|---|---|
committer | Kaim, Sean M <Sean.Kaim@ca.com> | 2015-11-04 23:46:18 +0300 |
commit | 1d0c3e474a4e2a935ae25932e731ac48c1a9ad1c (patch) | |
tree | 5242fb83e6a94100b5817e045c70904d4f9fb22e /callback.c | |
parent | b19b2a07ed187eda1315fe3a16986dab7cbba663 (diff) |
Merge upstream 0.65 tag
http://tartarus.org/~simon-git/gitweb/?p=putty.git;a=commit;h=7cfe83f7915907ea7cc2643468558e5bd83d4b51
Diffstat (limited to 'callback.c')
-rw-r--r-- | callback.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/callback.c b/callback.c new file mode 100644 index 00000000..c70dc53f --- /dev/null +++ b/callback.c @@ -0,0 +1,74 @@ +/* + * Facility for queueing callback functions to be run from the + * top-level event loop after the current top-level activity finishes. + */ + +#include <stddef.h> + +#include "putty.h" + +struct callback { + struct callback *next; + + toplevel_callback_fn_t fn; + void *ctx; +}; + +struct callback *cbhead = NULL, *cbtail = NULL; + +toplevel_callback_notify_fn_t notify_frontend = NULL; +void *frontend = NULL; + +void request_callback_notifications(toplevel_callback_notify_fn_t fn, + void *fr) +{ + notify_frontend = fn; + frontend = fr; +} + +void queue_toplevel_callback(toplevel_callback_fn_t fn, void *ctx) +{ + struct callback *cb; + + cb = snew(struct callback); + cb->fn = fn; + cb->ctx = ctx; + + /* If the front end has requested notification of pending + * callbacks, and we didn't already have one queued, let it know + * we do have one now. */ + if (notify_frontend && !cbhead) + notify_frontend(frontend); + + if (cbtail) + cbtail->next = cb; + else + cbhead = cb; + cbtail = cb; + cb->next = NULL; +} + +void run_toplevel_callbacks(void) +{ + if (cbhead) { + struct callback *cb = cbhead; + /* + * Careful ordering here. We call the function _before_ + * advancing cbhead (though, of course, we must free cb + * _after_ advancing it). This means that if the very last + * callback schedules another callback, cbhead does not become + * NULL at any point, and so the frontend notification + * function won't be needlessly pestered. + */ + cb->fn(cb->ctx); + cbhead = cb->next; + sfree(cb); + if (!cbhead) + cbtail = NULL; + } +} + +int toplevel_callback_pending(void) +{ + return cbhead != NULL; +} |