Condition variables
Condition variables are here defined as values that reside in shared heaps ([root:Netmcore_heap]), for example in the header field of [root: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.
The condition variable
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.
A special kind of wait_entry
for intergration into an event
loop
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.
A dummy condition is non-functional, but can be used to put something
into condition
-typed variables
A dummy wait_set
is non-functional, but can be used to put something
into wait_set
-typed variables
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.
Creates a wait_set
in the heap designated by the mutator
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.
Frees a wait_entry_e
. The named pipe is deleted.
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.
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.
signal c
restarts one of the processes waiting on the
condition variable c
.
broadcast c
restarts all processes waiting on the
condition variable c
.