Module Unblocker.Domain_local

Domain local unblockers.

Domain local unblockers

type unblock = block:bool -> bool

The type for action invocation unblocking functions.

A call to the function must unblock the action invocations that can synchronize. The block argument is such that:

  • If false the function must not block if there is nothing ready to unblock or nothing to unblock at all.
  • If true, the function must block until either an action invocation does unblock or until set_block_bypass is called. The scheduler ensure that a single local unblocker is invoked with ~block:true at the same time.

In all cases the function must return:

  • true if and only if it did sucessfully unblock (in the Private.Action.Blocked.synced_unblock_is_ours sense) at least one action invocation. False positive are ok but do not always return true as it may degenerate the scheduler into a busy waiting loop when there is no work.
  • false if no action invocation was unblocked by the call.

Warning. The function must not raise. If it does, the entity invoking the function should panic and not try to recover. If you have errors that happen because of user errors e.g. operations on a closed fd, you should either try discontinue the blocked action invocations and/or trap the exception so that it doesn't go unoticed. Do not trap asynchronous exceptions though.

type set_block_bypass = unit -> unit

The type for indicating that the next or current call to unblock with ~block:true, should not block.

If the call happens while unblock ~block:true is already naturally returning, the unblock call can clear the bypass or not, it's harmless. One way of thinking about this mecanism is to implement it using a self-pipe trick to unblock a blocking select(2); calling set_block_bypass makes the pipe readable until cleared (which is the responsability of unblock).

type t

The type for a per domain unblocker. It is guaranteed to be called only by the main thread of the domain it was created for, see Action.Unblocker.domain_local.

val make : unblock:unblock -> set_block_bypass:set_block_bypass -> unit -> t

make is a local unblocker with given properties. See accessors for details on how these functions end up being called by the scheduler.

val unblock : t -> block:bool -> bool

unblock u ~block tries to unblock primitive invocations. This is called by scheduler domains with block:false when they did not find work. If that doesn't unblock work they either go to sleep or if they are the last domain call the function again with block:true. See also unblock for details.

val set_block_bypass : t -> unit

set_block_bypass u indicates that the current or next blocking call to unblock should not block. This is used by the scheduler to unblock when new work is available and a domain is blocked with unblock ~block:true or on its way to do so. This is needed to coordinate schedulers with external entities which are unknown to the scheduler. See also set_block_bypass for details.

val none : t

none is an unblocker for when there is none. Trying to invoke its functions raise assertion failures.

Unblock nothing

val nothing : unit -> t

nothing is a local unblocker that unblocks nothing. It blocks by sleeping on a condition variable. It is used by the Unblocker.nothing unblocker.