module IVar:One-shot interprocess exceptions and variables.sig
..end
val with_interprocess_protect : (((unit -> 'a) -> 'a) -> 'b) -> 'b
with_interprocess_protect kont
calls kont
with one
argument, protect: (unit -> 'a) -> 'a
.
The function kont
must fork into an observer process and an
observed process. The observed process must not return from the
call to kont
; it must, however, call protect thunk
exactly
once with some thunk, which protect
will call. When kont
returns in the observer process, it blocks until the thunk
returns. If the thunk returns normally (or execs, or exits), then
protect thunk
returns the result of the thunk in the observed
process, and with_interprocess_protect
returns the result of
kont
in the observer process. However, if the thunk raises an
exception, then the observed process terminates with status 2 and
the call to with_interprocess_protect
in the observer
returns abnormally by re-raising the exception.
In this example, if Proc.exec
raises an exception in the child process,
then with_interprocess_protect
will re-raise that exception in
the parent process:
with_interprocess_protect
(fun protect ->
match Proc.fork () with
| None ->
protect (fun () -> Proc.exec prog args);
exit 3 (* can't happen *)
| Some proc -> proc)
val with_interprocess_raise_and_okay : ((exn -> unit) -> (unit -> unit) -> 'a) -> 'a
with_interprocess_raise_and_okay kont
calls kont
with two
arguments, {
oops : exn -> unit
okay : unit -> unit
}
The function kont
must fork into an observed process and an
observer process. When the call to kont
returns in
the observer process, with_interprocess_raise_and_okay
then
waits for either oops
or okay
to be called in the observed
process. If okay ()
is called, then it returns the result of
kont
; if oops e
is called, then it instead raises the exception
e
in the observer process. If the observed process fails to call
either oops
or okay
, then the observer process will block
indefinitely.
type 'a
read_end
type 'a
write_end
exception Dead
IVar
.
IVars allow (require, in fact) exactly one read and one write.val create : unit -> 'a read_end * 'a write_end
(r, w)
. The protocol is then as
follows. One process must execute:read r
write w v
: read returns Some v
close w
: read returns None
exec ...
: read returns None
exit ...
: read returns None
IVar.write
call may or may not block, depending on the underlying
implementation. In any case, it is imperative that read
happens in a separate process from the write/close/exec/exit, or
the program may block indefinitely.val read : 'a read_end -> 'a option
'a option
from an IVar
.
Blocks until the associated IVar.write_end
is written or closed.
If x
is written on the other end, returns Some x
; if
the other end is closed (including by exit or exec), returns
None
.val write : 'a write_end -> 'a -> unit
IVar
.val close : 'a write_end -> unit
IVar
without writing.