callback.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  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. #include <stddef.h>
  6. #include "putty.h"
  7. struct callback {
  8. struct callback *next;
  9. toplevel_callback_fn_t fn;
  10. void *ctx;
  11. };
  12. struct callback *cbhead = NULL, *cbtail = NULL;
  13. toplevel_callback_notify_fn_t notify_frontend = NULL;
  14. void *frontend = NULL;
  15. void request_callback_notifications(toplevel_callback_notify_fn_t fn,
  16. void *fr)
  17. {
  18. notify_frontend = fn;
  19. frontend = fr;
  20. }
  21. void queue_toplevel_callback(toplevel_callback_fn_t fn, void *ctx)
  22. {
  23. struct callback *cb;
  24. cb = snew(struct callback);
  25. cb->fn = fn;
  26. cb->ctx = ctx;
  27. /* If the front end has requested notification of pending
  28. * callbacks, and we didn't already have one queued, let it know
  29. * we do have one now. */
  30. if (notify_frontend && !cbhead)
  31. notify_frontend(frontend);
  32. if (cbtail)
  33. cbtail->next = cb;
  34. else
  35. cbhead = cb;
  36. cbtail = cb;
  37. cb->next = NULL;
  38. }
  39. void run_toplevel_callbacks(void)
  40. {
  41. if (cbhead) {
  42. struct callback *cb = cbhead;
  43. /*
  44. * Careful ordering here. We call the function _before_
  45. * advancing cbhead (though, of course, we must free cb
  46. * _after_ advancing it). This means that if the very last
  47. * callback schedules another callback, cbhead does not become
  48. * NULL at any point, and so the frontend notification
  49. * function won't be needlessly pestered.
  50. */
  51. cb->fn(cb->ctx);
  52. cbhead = cb->next;
  53. sfree(cb);
  54. if (!cbhead)
  55. cbtail = NULL;
  56. }
  57. }
  58. int toplevel_callback_pending(void)
  59. {
  60. return cbhead != NULL;
  61. }