|
| 1 | +(** A scheduler independent blocking mechanism. *) |
| 2 | + |
| 3 | +type mode = |
| 4 | + [ `Cancelable |
| 5 | + (** In the [`Cancelable] mode {!prepare_for_await} and {!t.await} are |
| 6 | + allowed to raise an (unspecified) exception that indicates that the |
| 7 | + caller's fiber has been canceled (and should terminate). If an |
| 8 | + exception is raised, then the caller should perform whatever cleanup is |
| 9 | + necessary to e.g. avoid space leaks. *) |
| 10 | + | `Protected |
| 11 | + (** In the [`Protected] mode {!prepare_for_await} and {!t.await} should act |
| 12 | + as if the caller's fiber has not been canceled. The [`Protected] mode |
| 13 | + should only be used in special cases such as when await might be needed |
| 14 | + during cleanup actions during stack unwinding. *) |
| 15 | + ] |
| 16 | +(** Specifies a mode of operation regarding cancellation. *) |
| 17 | + |
| 18 | +type t = { |
| 19 | + release : unit -> unit; |
| 20 | + (** [t.release ()] resumes the corresponding caller of [t.await ()] or |
| 21 | + does nothing in case the corresponding [t.await ()] has already |
| 22 | + resumed or the target fiber has been canceled. |
| 23 | +
|
| 24 | + {b NOTE}: An implementation of [t.release ()] should never fail. *) |
| 25 | + await : unit -> unit; |
| 26 | + (** [t.await ()] suspends the caller at most until [t.release ()] is |
| 27 | + called. *) |
| 28 | +} |
| 29 | +(** Represents an asynchronous trigger. |
| 30 | +
|
| 31 | + {b NOTE}: {!release} and {!await} should be domain safe and ideally |
| 32 | + optimized with the assumption that {!release} may be called multiple times |
| 33 | + and even before {!await} is called. Furthermore, {!await} may be called at |
| 34 | + most once. *) |
| 35 | + |
| 36 | +val prepare_for_await : mode -> t |
| 37 | +(** [prepare_for_await mode] prepares and returns a trigger [t] for (at most) |
| 38 | + one use of [t.await ()] by calling the [prepare] function registered for the |
| 39 | + current domain. |
| 40 | +
|
| 41 | + {b NOTE}: It is allowed for two different calls of [prepare_for_await] to |
| 42 | + return the same trigger and e.g. share a single trigger per domain or per |
| 43 | + fiber or even just have one single trigger. *) |
| 44 | + |
| 45 | +val using : prepare_for_await:(mode -> t) -> while_running:(unit -> 'a) -> 'a |
| 46 | +(** [using ~prepare_for_await ~while_running] registers the given asynchronous |
| 47 | + trigger mechanism for the current domain for the duration of running the |
| 48 | + given scheduler. In other words, this sets the implementation of |
| 49 | + {!prepare_for_await} for the current domain. |
| 50 | +
|
| 51 | + {b NOTE}: The given [prepare_for_await] function is called every time |
| 52 | + {!prepare_for_await} is called while the scheduler is running. |
| 53 | +
|
| 54 | + {b NOTE}: This is normally only called by libraries that implement |
| 55 | + schedulers and the specified [prepare_for_await] typically returns a trigger |
| 56 | + mechanism {!t} that tightly integrates with the scheduler by e.g. performing |
| 57 | + an effect to suspend the current fiber when {!t.await} is called. *) |
0 commit comments