aboutsummaryrefslogtreecommitdiff
path: root/tools/plink/callback.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2014-04-14 23:54:46 +0200
committermarha <marha@users.sourceforge.net>2014-04-14 23:54:46 +0200
commit5e46f2bc0fb67bef982e71a47e6dc1aa646eee3b (patch)
tree83444e4115639718c44d0db2eed0fe206355afbe /tools/plink/callback.c
parent3b338661b1f42161e11ac36bb5ecce8d175df783 (diff)
parent64e01951590b2856a10dd0cadd14de2b855daad0 (diff)
downloadvcxsrv-5e46f2bc0fb67bef982e71a47e6dc1aa646eee3b.tar.gz
vcxsrv-5e46f2bc0fb67bef982e71a47e6dc1aa646eee3b.tar.bz2
vcxsrv-5e46f2bc0fb67bef982e71a47e6dc1aa646eee3b.zip
Merge remote-tracking branch 'origin/released'
Diffstat (limited to 'tools/plink/callback.c')
-rw-r--r--tools/plink/callback.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/tools/plink/callback.c b/tools/plink/callback.c
new file mode 100644
index 000000000..c70dc53fb
--- /dev/null
+++ b/tools/plink/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;
+}