event.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /* Definitions for event handling.
  2. This file is part of khipu.
  3. khipu is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. #include "event.hpp"
  14. #include "thread.hpp"
  15. #include "function.hpp"
  16. #include "memory.hpp"
  17. #include "symbol.hpp"
  18. #include "str.hpp"
  19. KP_DECLS_BEGIN
  20. static object ev_handlers[NPENDEV + 1];
  21. #ifdef KP_PLATFORM_UNIX
  22. static result<object>
  23. sigint_handler (interpreter *interp, object *, int)
  24. {
  25. return (interp->raise ("intr-error", "thread was interrupted"));
  26. }
  27. static void
  28. sighandler (int sig)
  29. {
  30. interpreter::self()->set_ev (sig);
  31. }
  32. #endif
  33. object add_evhandler (interpreter *interp, unsigned int ev, object fct)
  34. {
  35. if (--ev >= NPENDEV)
  36. kp_return (UNBOUND);
  37. object *ptr = &ev_handlers[ev];
  38. if (singlethr_p ())
  39. {
  40. interp->retval = *ptr;
  41. *ptr = fct;
  42. }
  43. else
  44. interp->retval = atomic_swap ((atomic_t *)ptr, fct);
  45. return (interp->retval);
  46. }
  47. object get_evhandler (interpreter *interp, unsigned int ev)
  48. {
  49. if (--ev >= NPENDEV)
  50. kp_return (UNBOUND);
  51. kp_return (ev_handlers[ev]);
  52. }
  53. struct builtin_event
  54. {
  55. native_function fct;
  56. string name;
  57. symbol sym;
  58. void init (interpreter *interp, const void *data,
  59. native_function::fn_type fn, int idx)
  60. {
  61. this->name.local_init (data);
  62. this->sym.vo_type = typecode::SYMBOL;
  63. this->sym.value = UNBOUND;
  64. this->sym.pkg = NIL;
  65. this->sym.name = ensure_mask(&this->name)->as_obj ();
  66. this->fct.vo_full = function_base::native_flag;
  67. this->fct.vo_type = typecode::FCT;
  68. this->fct.min_argc = this->fct.max_argc = 1;
  69. this->fct.name = ensure_mask(&this->sym)->as_obj ();
  70. this->fct.fct = fn;
  71. ev_handlers[idx - 1] = ensure_mask(&this->fct)->as_obj ();
  72. }
  73. };
  74. static int
  75. do_init_events (interpreter *interp)
  76. {
  77. int ret = init_op::call_deps (interp, &init_symbols);
  78. if (ret != init_op::result_ok)
  79. return (ret);
  80. for (unsigned int i = 0; i < NPENDEV; ++i)
  81. ev_handlers[i] = UNBOUND;
  82. #ifdef KP_PLATFORM_UNIX
  83. static builtin_event sigint_event;
  84. sigint_event.init (interp, "sigint-handler", sigint_handler, SIGINT);
  85. struct sigaction sa;
  86. sigfillset (&sa.sa_mask);
  87. sa.sa_flags = 0;
  88. sa.sa_handler = sighandler;
  89. sigaction (SIGINT, &sa, 0);
  90. #endif
  91. static builtin_event gcreq_event;
  92. gcreq_event.init (interp, "gc-request", gcreq_handler, GCREQ_EV);
  93. return (init_op::result_ok);
  94. }
  95. init_op init_event (do_init_events, "events");
  96. KP_DECLS_END