123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- /* Definitions for event handling.
- This file is part of khipu.
- khipu is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
- #include "event.hpp"
- #include "thread.hpp"
- #include "function.hpp"
- #include "memory.hpp"
- #include "symbol.hpp"
- #include "str.hpp"
- KP_DECLS_BEGIN
- static object ev_handlers[NPENDEV + 1];
- #ifdef KP_PLATFORM_UNIX
- static result<object>
- sigint_handler (interpreter *interp, object *, int)
- {
- return (interp->raise ("intr-error", "thread was interrupted"));
- }
- static void
- sighandler (int sig)
- {
- interpreter::self()->set_ev (sig);
- }
- #endif
- object add_evhandler (interpreter *interp, unsigned int ev, object fct)
- {
- if (--ev >= NPENDEV)
- kp_return (UNBOUND);
- object *ptr = &ev_handlers[ev];
- if (singlethr_p ())
- {
- interp->retval = *ptr;
- *ptr = fct;
- }
- else
- interp->retval = atomic_swap ((atomic_t *)ptr, fct);
- return (interp->retval);
- }
- object get_evhandler (interpreter *interp, unsigned int ev)
- {
- if (--ev >= NPENDEV)
- kp_return (UNBOUND);
- kp_return (ev_handlers[ev]);
- }
- struct builtin_event
- {
- native_function fct;
- string name;
- symbol sym;
- void init (interpreter *interp, const void *data,
- native_function::fn_type fn, int idx)
- {
- this->name.local_init (data);
- this->sym.vo_type = typecode::SYMBOL;
- this->sym.value = UNBOUND;
- this->sym.pkg = NIL;
- this->sym.name = ensure_mask(&this->name)->as_obj ();
- this->fct.vo_full = function_base::native_flag;
- this->fct.vo_type = typecode::FCT;
- this->fct.min_argc = this->fct.max_argc = 1;
- this->fct.name = ensure_mask(&this->sym)->as_obj ();
- this->fct.fct = fn;
- ev_handlers[idx - 1] = ensure_mask(&this->fct)->as_obj ();
- }
- };
- static int
- do_init_events (interpreter *interp)
- {
- int ret = init_op::call_deps (interp, &init_symbols);
- if (ret != init_op::result_ok)
- return (ret);
- for (unsigned int i = 0; i < NPENDEV; ++i)
- ev_handlers[i] = UNBOUND;
- #ifdef KP_PLATFORM_UNIX
- static builtin_event sigint_event;
- sigint_event.init (interp, "sigint-handler", sigint_handler, SIGINT);
- struct sigaction sa;
- sigfillset (&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = sighandler;
- sigaction (SIGINT, &sa, 0);
- #endif
- static builtin_event gcreq_event;
- gcreq_event.init (interp, "gc-request", gcreq_handler, GCREQ_EV);
- return (init_op::result_ok);
- }
- init_op init_event (do_init_events, "events");
- KP_DECLS_END
|