1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374openCoremoduleSignal=Core.SignalmoduleHandlers=structtypet={bag:((Signal.t->unit)[@sexp.opaque])Bag.t}[@@derivingsexp_of]letcreate()={bag=Bag.create()}letaddthandler=Bag.addt.baghandlerletremovethandler_elt=Bag.removet.baghandler_eltletdelivertsignal=Bag.itert.bag~f:(funhandler->tryhandlersignalwith|exn->raise_s[%message"signal handler unexpectedly raised"(exn:exn)]);;endtypedelivered=(Signal.t*Handlers.t)Thread_safe_queue.ttypet={handlers_by_signal:Handlers.tSignal.Table.t;delivered:(delivered[@sexp.opaque]);thread_safe_notify_signal_delivered:unit->unit}[@@derivingsexp_of]letinvariant_=()letcreate~thread_safe_notify_signal_delivered={handlers_by_signal=Signal.Table.create();delivered=Thread_safe_queue.create();thread_safe_notify_signal_delivered};;letis_managingtsignal=Hashtbl.memt.handlers_by_signalsignalmoduleHandler=structtypet=Tof(Handlers.t*(Signal.t->unit)Bag.Elt.t)listendtypehandler=Handler.tletget_handlerstsignal=Hashtbl.find_or_addt.handlers_by_signalsignal~default:(fun()->lethandlers=Handlers.create()inSignal.Expert.handlesignal(fun_->(* Everything in this function body must be thread safe, since it is running in an
OCaml signal handler. *)Thread_safe_queue.enqueuet.delivered(signal,handlers);t.thread_safe_notify_signal_delivered());handlers);;letmanagetsignal=ignore(get_handlerstsignal:Handlers.t)letinstall_handlertsignalshandler=Handler.T(List.mapsignals~f:(funsignal->lethandlers=get_handlerstsignalinhandlers,Handlers.addhandlershandler));;letremove_handler_t(Handler.Thandler)=List.iterhandler~f:(fun(handlers,handler_elt)->Handlers.removehandlershandler_elt);;lethandle_deliveredt=whileThread_safe_queue.lengtht.delivered>0doletsignal,handlers=Thread_safe_queue.dequeue_exnt.deliveredinHandlers.deliverhandlerssignaldone;;