1
(* $Id: netplex_semaphore.mli 1569 2011-04-05 16:08:52Z gerd $ *)
3
(** Netplex-wide semaphores *)
7
(** Semaphores are counters with atomic increment and decrement operations.
8
They are very useful for counting the number of uses of a shared
9
resource, and allow the identification of the first use (so the resource
10
must be made available at all), and the last use (the resource can be
13
This implementation works in both multi-processing and
14
multi-threading netplex environments. It is, however, not very
15
fast, because the counters live in the controller, and the
16
increment/decrement operations are realized by RPC's. It is good
17
enough when these operations are only infrequently called, e.g. in
18
the post-start and pre-finish processor callbacks.
20
This interface is designed so that a later re-implementation with
21
POSIX semaphores is relatively straight-forward.
25
(** To enable semaphores, call the controller's [add_plugin] method
26
with this object as argument. This can e.g. be done in the
27
[post_add_hook] of the processor.
31
(** The following functions can {b only} be invoked in container
32
contexts. Outside of such a context the exception
33
{!Netplex_cenv.Not_in_container_thread} is raised.
36
val increment : string -> int64
37
(** Increment the named semaphore by 1, and return the new value.
38
If the semaphore does not exist yet, it is created with an initial
39
value of 0, which is then incremented.
41
Semaphore names are global to the whole netplex system. By convention,
42
these names are formed like ["service_name.local_name"], i.e. they
43
are prefixed by the socket service to which they refer.
46
val decrement : ?wait:bool -> string -> int64
47
(** Decrement the named semaphore by 1, and return the new value.
48
Semaphore values cannot become negative. If the value is already 0,
49
it is not decremented anymore if [wait = false]. However, (-1)
50
is then returned nevertheless.
52
If the value is already 0 and [wait=true], the operation waits until
53
the value exceeds 0, and when this happens, the semaphore is then
54
decremented again. If several waiters exist, only one waiter gets
55
the chance to decrement.
58
val get : string -> int64
59
(** Get the value of the named semaphore. Useful e.g. for monitoring
60
the semaphore. If the semaphore does not exist, a value of 0 is
63
[get] can also be invoked from the controller process.
66
val create : ?protected:bool -> string -> int64 -> bool
67
(** Create the semaphore with this initial value. Returns [true] if the
68
creation is successful, and [false] if the semaphore already existed.
70
If [protected], the semaphore
71
is automatically decremented by some value when the container
72
calling this function terminates. This value is [pi - d] where
73
[pi] is the number of increments and [d] is the number
74
of (successful) decrements requested by the container.
76
A semaphore needs not to be explicitly created by calling [create].
77
It is automatically created at the first use time with a value of 0
80
[create] can also be invoked from the controller process.
83
val destroy : string -> unit
84
(** Destroy this semaphore. Any waiting [decrement] will immediately
87
Note that there is no protection against unintended re-creation
90
[destroy] can also be invoked from the controller process.
93
val ctrl_increment : string -> Netplex_types.container_id -> int64
94
(** Increment the named semaphore from controller context, substituting
95
an increment from a container (e.g. a container that terminated
96
or is otherwise no longer able to do so). In this
97
case the ID of the container needs to be passed
101
(** Example (code fragment):
103
Override the processor callbacks as follows to count the number of
104
containers for the service:
107
method post_add_hook sockserv ctrl =
108
ctrl # add_plugin Netplex_semaphore.plugin
110
method post_start_hook container =
111
let sem_name = container#socket_service#name ^ ".counter" in
113
Netplex_semaphore.increment sem_name in
115
prerr_endline "First container"
117
method pre_finish_hook container =
118
let sem_name = container#socket_service#name ^ ".counter" in
120
Netplex_semaphore.decrement sem_name in
122
prerr_endline "Last container"