package picos
Install
dune-project
Dependency
Authors
Maintainers
Sources
sha256=544804c0bde4b29764f82f04e7defed7c06bc43e5a6ce3f7fdc326cb54a7f066
sha512=4c93427e477fb52374a554a8b9c4c92836a9b5899161275d1473269ab526a1f59177209140631ed763a55be375855dea12f076e18bf4124522414986c0e257be
doc/picos.select/Picos_select/index.html
Module Picos_selectSource
Basic Unix.select based IO event loop for Picos.
The operations in this module automatically manage a Thread per domain that runs a Unix.select loop to support the operations.
⚠️ Signal handlers are unfortunately fundamentally non-compositional. The use of signal handlers in this module has been designed to be configurable, which should allow co-operating with other libraries using signals as long as care is taken at application startup to configure things.
⚠️ All the usual limitations of the Unix module apply.
API
Timeouts
cancel_after computation ~seconds exn_bt arranges for computation to be canceled with given exn_bt after given time in seconds. Completion of the computation before the specified time effectively cancels the timeout.
ℹ️ You can use cancel_after to implement the handler for the Cancel_after effect.
IO
return_on computation fd op value arranges for computation to be returned with given value when fd becomes available for op. Completion of the computation before the fd becomes available for op effectively cancels the arrangement.
ℹ️ Using Unix.set_nonblock and return_on you can implement direct-style transparently asynchronous IO on top of the Unix module.
await_on fd op awaits until fd becomes available for op.
Processes
return_on_sigchld computation value arranges for computation to be returned with given value on next Sys.sigchld. Completion of the computation before a Sys.sigchld is received effectively cancels the arrangement.
⚠️ The mechanism uses the Sys.sigchld signal which should not be used for other purposes.
Configuration
configure ~intr_sig ~handle_sigchld () can, and sometimes must, be called by an application to configure the use of signals by this module.
The optional intr_sig argument can be used to specify the signal used by the interrupt mechanism. The default is to use Sys.sigusr2.
The optional handle_sigchld argument can be used to specify whether this module should setup handling of Sys.sigchld. The default is true. When explicitly specified as ~handle_sigchld:false, the application should arrange to call handle_signal whenever a Sys.sigchld signal occurs.
⚠️ This module must always be configured before use. Unless this module has been explicitly configured, calling a method of this module from the main thread on the main domain will automatically configure this module with default options. In case the application uses multiple threads or multiple domains, the application should arrange to call configure from the main thread on the main domain before any threads or domains besides the main are created or spawned.
handle_signal signum should be called to notify this module of a signal when configured to not handle said signals.
check_configured () checks whether this module has already been configured or not and, if not, calls configure with default arguments.
ℹ️ The intended use case for check_configure () is at the point of entry of schedulers and other facilities that use this module.
Examples
First we open some modules for convenience:
open Picos
open Picos_structured.Finally
open Picos_structured
open Picos_stdioOne of many
Here is an example that awaits for one of multiple alternative events:
# exception Timeout
exception Timeout
# Picos_fifos.run ~forbid:false @@ fun () ->
let@ msg_inn1, msg_out1 =
finally Unix.close_pair @@ fun () ->
Unix.socketpair PF_UNIX SOCK_STREAM 0 ~cloexec:true
in
let@ msg_inn2, msg_out2 =
finally Unix.close_pair @@ fun () ->
Unix.socketpair PF_UNIX SOCK_STREAM 0 ~cloexec:true
in
let@ syn_inn, syn_out =
finally Unix.close_pair @@ fun () ->
Unix.socketpair PF_UNIX SOCK_STREAM 0 ~cloexec:true
in
Unix.set_nonblock msg_inn1;
Unix.set_nonblock msg_out1;
Unix.set_nonblock msg_inn2;
Unix.set_nonblock msg_out2;
Unix.set_nonblock syn_inn;
Unix.set_nonblock syn_out;
Bundle.join_after begin fun bundle ->
Bundle.fork bundle begin fun () ->
while true do
let select = Computation.create () in
Picos_select.return_on select msg_inn1 `R `Inn1;
Picos_select.return_on select msg_inn2 `R `Inn2;
Picos_select.cancel_after select
~seconds:0.1 (Exn_bt.get_callstack 0 Timeout);
match Computation.await select with
| `Inn1 ->
Printf.printf "Inn1\n%!";
assert (1 = Unix.read msg_inn1 (Bytes.create 1) 0 1);
assert (1 = Unix.write_substring syn_out "!" 0 1)
| `Inn2 ->
Printf.printf "Inn2\n%!";
assert (1 = Unix.read msg_inn2 (Bytes.create 1) 0 1);
assert (1 = Unix.write_substring syn_out "!" 0 1)
| exception Timeout ->
Printf.printf "Timeout\n%!";
assert (1 = Unix.write_substring syn_out "!" 0 1)
| exception exn ->
Computation.cancel select (Exn_bt.get_callstack 0 Exit);
raise exn
done
end;
assert (1 = Unix.write_substring msg_out1 "!" 0 1);
assert (1 = Unix.read syn_inn (Bytes.create 1) 0 1);
assert (1 = Unix.write_substring msg_out2 "!" 0 1);
assert (1 = Unix.read syn_inn (Bytes.create 1) 0 1);
assert (1 = Unix.read syn_inn (Bytes.create 1) 0 1);
Bundle.terminate bundle
end
Inn1
Inn2
Timeout
- : unit = ()This approach of using the completion of a computation to select one of multiple events can be generalized.