1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677openPicostype'afinally=('a->unit)*(unit->'a)let[@inline]finallyreleaseacquire=(release,acquire)(** This function is marked [@inline never] to ensure that there are no
allocations between the [acquire ()] and the [match ... with] nor before
[release]. Allocations here would mean that e.g. pressing Ctrl-C, i.e.
[SIGINT], at the right moment could mean that [release] would not be called
after [acquire]. *)let[@inlinenever](let@)(release,acquire)body=letx=acquire()inmatchbodyxwith|y->releasex;y|exceptionexn->releasex;raiseexntype('a,_)tdt=|Nothing:('a,[>`Nothing])tdt|Resource:{mutableresource:'a;release:'a->unit;moved:Trigger.t;}->('a,[>`Resource])tdttype'amoveable=('a,[`Nothing|`Resource])tdtAtomic.tlet(let^)(release,acquire)body=letmoveable=Atomic.makeNothinginletacquire()=let(Resourcerasstate:(_,[`Resource])tdt)=Resource{resource=Obj.magic();release;moved=Trigger.create()}inr.resource<-acquire();Atomic.setmoveablestate;moveableinletreleasemoveable=matchAtomic.getmoveablewith|Nothing->()|Resourcer->beginmatchTrigger.awaitr.movedwith|None->()|Someexn_bt->beginmatchAtomic.exchangemoveableNothingwith|Nothing->()|Resourcer->r.releaser.resource;Exn_bt.raiseexn_btendendin(let@)(release,acquire)bodylet[@inlinenever]check_no_resource()=(* In case of cancelation this is not considered an error as the resource was
(likely) released by the parent. *)Fiber.check(Fiber.current());invalid_arg"no resource to move"letmovemoveable=matchAtomic.getmoveablewith|Nothing->check_no_resource()|Resourcer->letacquire()=matchAtomic.exchangemoveableNothingwith|Nothing->check_no_resource()|Resourcer->Trigger.signalr.moved;r.resourcein(r.release,acquire)