# Module Netmcore_condition

    module Netmcore_condition: sig .. end

Condition variables

Condition variables are here defined as values that reside in shared heaps (`Netmcore_heap`), for example in the header field of `Netmcore_array` or somewhere else in heap-allocated data structures.

In order to ensure that the condition variable is in the heap, the special function `create_condition` must be used to initialize it there. As `create_condition` requires a mutator as argument, this is only possible by calling `create_condition` from the callback of `Netmcore_heap.modify`.

Condition variables are special values, and cannot be copied or moved.

Condition variables are implemented on top of semaphores. Compared to the `pthreads` version of condition variables, the user needs here to allocate special `wait_entry` slots, one for each process. An entry can be used for all condition variables a process needs to wait for. (Actually, such entries also exist in typical `pthreads` implementations, but are hidden from the user in the thread control block. We just don't have here a place where we could allocate process-specific shared memory.)

Since Ocamlnet-3.5, there are also special wait entries `wait_entry_e` which can be used to wait from within a running Unixqueue. For each such wait entry, however, a named pipe needs to be allocated.

    type condition

The condition variable

    type wait_entry

Each process that wants to `wait` needs a `wait_entry`. These entries can be used for several condition variables, so typically each process has only one entry for each heap.

    type wait_entry_e

A special kind of `wait_entry` for intergration into an event loop

    type wait_set

A set of `wait_entry`, for easier management. This set can e.g. be stored side by side with the condition variable(s). It is important that the `wait_set` resides in the same shared heap as the condition variable.

    val dummy_condition : unit -> condition

A dummy condition is non-functional, but can be used to put something into `condition`-typed variables

    val dummy_wait_set : unit -> wait_set

A dummy `wait_set` is non-functional, but can be used to put something into `wait_set`-typed variables

    val create_condition : Netmcore_heap.mutator -> condition

`create m`: Creates a condition variable, and pushes it to the heap, using the mutator `m`.

After being pushed to the heap, the variable can be used. It is nonsense to copy it outside the heap.

    val create_wait_set : Netmcore_heap.mutator -> wait_set

Creates a `wait_set` in the heap designated by the mutator

    val alloc_wait_entry : Netmcore_heap.mutator ->
           wait_set -> wait_entry

Allocates a `wait_entry`

    val free_wait_entry : Netmcore_heap.mutator ->
           wait_set -> wait_entry -> unit

Frees a `wait_entry`

    val alloc_wait_entry_e : Netmcore_heap.mutator ->
           wait_set -> string -> wait_entry_e

`alloc_wait_entry_e mut set filename`: Allocates a new wait entry with notification via named pipe. The `filename` must refer to an existing named pipe.

    val free_wait_entry_e : Netmcore_heap.mutator ->
           wait_set -> wait_entry_e -> unit

Frees a `wait_entry_e`. The named pipe is deleted.

    val wait : wait_entry ->
           condition -> Netmcore_mutex.mutex -> unit

`wait we c m` atomically unlocks the mutex `m` and suspends the calling process on the condition variable `c`. The process will restart after the condition variable `c` has been signalled. The mutex `m` is locked again before `wait` returns.

At the time of calling, the `wait_entry` `we` must not be used to manage another `wait`. When allocating a separate `wait_entry` per process this problem does not occur.

    val wait_e : ?debug_name:string ->
           wait_entry_e ->
           condition ->
           Netmcore_mutex.mutex ->
           Unixqueue.event_system ->
           (unit -> 'a Uq_engines.engine) -> 'a Uq_engines.engine

Like `wait`, but the suspension is done by waiting on a named pipe event (i.e. "nonblocking suspension"):

`wait_e we c m esys cont` atomically unlocks the mutex `m` and suspends the calling engine on the condition variable `c`. The engine will restart after the condition variable `c` has been signalled. The mutex `m` is locked again, at which time `cont` is called. The result of `cont()` is the result of `wait_e`.

At the time of calling, the `wait_entry_e` `we` must not be used to manage another `wait_e`. When allocating a separate `wait_entry_e` per process (or thread within the process) this problem does not occur.

    val signal : condition -> unit

`signal c` restarts one of the processes waiting on the condition variable `c`.

    val broadcast : condition -> unit

`broadcast c` restarts all processes waiting on the condition variable `c`.

    val pipe_name : wait_entry_e -> string

Returns the name of the pipe

    val destroy_condition : condition -> unit

    val destroy_wait_set : wait_set -> unit

Destroys these objects

    module Debug: sig .. end