123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172openPicostypet={fiber:Fiber.t;mutex:Mutex.t;condition:Condition.t}letcreate~forbidcomputation=letfiber=Fiber.create~forbidcomputationinletmutex=Mutex.create()inletcondition=Condition.create()in{fiber;mutex;condition}letblocktriggert=(* We block fibers (or threads) on a per thread mutex and condition. *)Mutex.lockt.mutex;matchwhilenot(Trigger.is_signaledtrigger)doCondition.waitt.conditiont.mutexdonewith|()->Mutex.unlockt.mutex|exceptionexn->(* Condition.wait may be interrupted by asynchronous exceptions and we
must make sure to unlock even in that case. *)Mutex.unlockt.mutex;raiseexnletresumetriggert_=let_is_canceled:bool=Fiber.unsuspendt.fibertriggerin(* This will be called when the trigger is signaled. We simply broadcast on
the per thread condition variable. *)Mutex.lockt.mutex;Mutex.unlockt.mutex;Condition.broadcastt.conditionlet[@alert"-handler"]recawaitttrigger=ifFiber.try_suspendt.fibertriggerttresumethenblocktriggert;Fiber.canceledt.fiberandcurrentt=(* The current handler must never propagate cancelation, but it would be
possible to yield here to run some other fiber before resuming the current
fiber. *)t.fiberandyieldt=(* In other handlers we need to account for cancelation. *)Fiber.checkt.fiber;Systhreads.yield()andcancel_after:typea._->aComputation.t->_=(* We need an explicit type signature to allow OCaml to generalize the tyoe as
all of the handlers are in a single recursive definition. *)funtcomputation~secondsexn_bt->Fiber.checkt.fiber;Select.cancel_aftercomputation~secondsexn_btandspawn:typea._->forbid:bool->aComputation.t->_=funt~forbidcomputationmains->Fiber.checkt.fiber;mains|>List.iter@@funmain->Systhreads.create(fun()->(* We need to (recursively) install the handler on each new thread
that we create. *)Handler.usinghandler(create~forbidcomputation)main)()|>ignoreandhandler=Handler.{current;spawn;yield;cancel_after;await}letrun~forbidmain=Handler.usinghandler(create~forbid(Computation.create()))main