1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495exceptionTimeoutclassvirtual['a]clock_base=objectmethodvirtualnow:'amethodvirtualsleep_until:'a->unitendclassvirtualclock=objectinherit[float]clock_baseendletnow(t:_#clock_base)=t#nowletsleep_until(t:_#clock_base)time=t#sleep_untiltimeletsleeptd=sleep_untilt(nowt+.d)moduleMono=structclassvirtualt=objectinherit[Mtime.t]clock_baseendletnow=nowletsleep_until=sleep_untilletsleep_spantspan=matchMtime.add_span(nowt)spanwith|Sometime->sleep_untilttime|None->Fiber.await_cancel()(* Converting floats via int64 is tricky when things overflow or go negative.
Since we don't need to wait for more than 100 years, limit it to this: *)lettoo_many_ns=0x8000000000000000.letspan_of_ss=ifs>=0.0then(letns=s*.1e9inifns>=too_many_nsthenMtime.Span.max_spanelseMtime.Span.of_uint64_ns(Int64.of_floatns))elseMtime.Span.zero(* Also happens for NaN and negative infinity *)letsleep(t:#t)s=sleep_spant(span_of_ss)endletwith_timeouttd=Fiber.first(fun()->sleeptd;Error`Timeout)letwith_timeout_exntd=Fiber.first(fun()->sleeptd;raiseTimeout)moduleTimeout=structtypet=|TimeoutofMono.t*Mtime.Span.t|Deprecatedofclock*float|Unlimitedletnone=Unlimitedletvclocktime=Timeout((clock:>Mono.t),time)letsecondsclocktime=vclock(Mono.span_of_stime)letof_sclocktime=Deprecated((clock:>clock),time)letruntfn=matchtwith|Unlimited->fn()|Timeout(clock,d)->Fiber.first(fun()->Mono.sleep_spanclockd;Error`Timeout)fn|Deprecated(clock,d)->Fiber.first(fun()->sleepclockd;Error`Timeout)fnletrun_exntfn=matchtwith|Unlimited->fn()|Timeout(clock,d)->Fiber.first(fun()->Mono.sleep_spanclockd;raiseTimeout)fn|Deprecated(clock,d)->Fiber.first(fun()->sleepclockd;raiseTimeout)fnletpp_durationfd=ifd>=0.001&&d<0.1thenFmt.pff"%.2gms"(d*.1000.)elseifd<120.thenFmt.pff"%.2gs"delseFmt.pff"%.2gm"(d/.60.)letppf=function|Unlimited->Fmt.stringf"(no timeout)"|Timeout(_clock,d)->letd=Mtime.Span.to_float_nsd/.1e9inpp_durationfd|Deprecated(_clock,d)->pp_durationfdend