]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - callback.c
first pass
[PuTTY.git] / callback.c
1 /*
2  * Facility for queueing callback functions to be run from the
3  * top-level event loop after the current top-level activity finishes.
4  */
5
6 #include <stddef.h>
7
8 #include "putty.h"
9
10 struct callback {
11     struct callback *next;
12
13     toplevel_callback_fn_t fn;
14     void *ctx;
15 };
16
17 struct callback *cbhead = NULL, *cbtail = NULL;
18
19 toplevel_callback_notify_fn_t notify_frontend = NULL;
20 void *frontend = NULL;
21
22 void request_callback_notifications(toplevel_callback_notify_fn_t fn,
23                                     void *fr)
24 {
25     notify_frontend = fn;
26     frontend = fr;
27 }
28
29 void queue_toplevel_callback(toplevel_callback_fn_t fn, void *ctx)
30 {
31     struct callback *cb;
32
33     cb = snew(struct callback);
34     cb->fn = fn;
35     cb->ctx = ctx;
36
37     /* If the front end has requested notification of pending
38      * callbacks, and we didn't already have one queued, let it know
39      * we do have one now. */
40     if (notify_frontend && !cbhead)
41         notify_frontend(frontend);
42
43     if (cbtail)
44         cbtail->next = cb;
45     else
46         cbhead = cb;
47     cbtail = cb;
48     cb->next = NULL;
49 }
50
51 void run_toplevel_callbacks(void)
52 {
53     if (cbhead) {
54         struct callback *cb = cbhead;
55         /*
56          * Careful ordering here. We call the function _before_
57          * advancing cbhead (though, of course, we must free cb
58          * _after_ advancing it). This means that if the very last
59          * callback schedules another callback, cbhead does not become
60          * NULL at any point, and so the frontend notification
61          * function won't be needlessly pestered.
62          */
63         cb->fn(cb->ctx);
64         cbhead = cb->next;
65         sfree(cb);
66         if (!cbhead)
67             cbtail = NULL;
68     }
69 }
70
71 int toplevel_callback_pending(void)
72 {
73     return cbhead != NULL;
74 }