module Uq_engines:An engine performs a certain task in an autonomous way. Engines are attached to asig..end
Unixqueue.event_system, and do their task by
generating events for resources of the operating system, and
by handling such events. Engines are in one of four states: They
may be still working, they may be done, they may be
aborted, or they may be in an error state. The three latter
states a called final states, because they indicate that the
engine has stopped operation.
It is possible to ask an engine to notify another object when it
changes its state. For simplicity, notification is done by invoking
a callback function, and not by issuing notification events.
exception Closed_channel
This exception should be regarded as equivalent to
Netchannels.Closed_channel, but it is not the same exception.
exception Broken_communication
This exception is not raised, but used as argument of the `Error
state.
exception Watchdog_timeout
This exception is not raised, but used as argument of the `Error
state.
exception Addressing_method_not_supported
client_socket_connector and server_socket_acceptor to
indicate that the passed address is not supported by the class.type'aengine_state =[ `Aborted | `Done of 'a | `Error of exn | `Working of int ]
't:`Working n: The engine is working. The number n counts the number
of events that have been processed.`Done arg: The engine has completed its task without errors.
The argument arg is the result value of the engine`Error exn: The engine has aborted because of an error. The
argument exn describes the error as an exception.`Aborted: The engine has aborted because the abort method
was calledclass type['a]engine =object..end
val when_state : ?is_done:('a -> unit) ->
?is_error:(exn -> unit) ->
?is_aborted:(unit -> unit) -> 'a #engine -> unit
is_done : The state transitions to `Done. The argument of
is_done is the argument of the `Done state.is_error : The state transitions to `Error. The argument of
is_error is the argument of the `Error state.is_aborted : The state transitions to `Aborted.class[['a, 'b]]map_engine :map_done:'a -> 'b engine_state -> ?map_error:exn -> 'b engine_state -> ?map_aborted:unit -> 'b engine_state -> 'a #engine ->['b]engine
map_engine observes the argument engine, and when the
state changes to `Done, `Error, or `Aborted, the corresponding
mapping function is called, and the resulting state becomes the state
of the mapped engine.
class['a]const_engine :'a engine_state -> Unixqueue.event_system ->['a]engine
`Working 0 in one
step to the passed constant state.
class[['a, 'b]]seq_engine :'a #engine -> 'a -> 'b #engine ->['b]engine
class[['a, 'b]]sync_engine :'a #engine -> 'b #engine ->[('a * 'b)]engine
`Done (synchronization).
class poll_engine :?extra_match:exn -> bool -> (Unixqueue.operation * float) list -> Unixqueue.event_system ->object..end
class poll_process_engine :?period:float -> pid:int -> Unixqueue.event_system ->[Unix.process_status]engine
pid terminates.
class watchdog :float -> 'a #engine ->[unit]engine
`Error Watchdog_timeout.
class type async_out_channel =object..end
class type async_in_channel =object..end
class receiver :src:Unix.file_descr -> dst:#async_out_channel -> ?close_src:bool -> ?close_dst:bool -> Unixqueue.event_system ->[unit]engine
src file descriptor to the
dst output channel.
class sender :src:#async_in_channel -> dst:Unix.file_descr -> ?close_src:bool -> ?close_dst:bool -> Unixqueue.event_system ->[unit]engine
src input channel to the
dst file descriptor.
class output_async_descr :dst:Unix.file_descr -> ?buffer_size:int -> ?close_dst:bool -> Unixqueue.event_system ->object..end
async_out_channel for the output
descriptor dst.
input_async_descr, is not yet written. Such a class does not provide
new functionality, as one can always read with receiver from
file descriptors, and this is even the preferable way.typecopy_task =[ `Bidirectional of Unix.file_descr * Unix.file_descr
| `Tridirectional of Unix.file_descr * Unix.file_descr * Unix.file_descr
| `Uni_socket of Unix.file_descr * Unix.file_descr
| `Unidirectional of Unix.file_descr * Unix.file_descr ]
copier class has to do:
`Unidirectional(src,dst): Data from src are copied to dst.
EOF of src causes that both descriptors are closed.`Uni_socket(src,dst): Data from src are copied to dst.
EOF of src causes that dst is shut down for sending; all descriptors
remain open. It is required that dst is a socket.`Bidirectional(bi1,bi2): Data from bi1 are copied to bi2,
and data from bi2 are copied to bi1. EOF of one descriptor
causes that the other descriptor is shut down for sending.
When both descriptors are at EOF, both are closed.
It is required that bi1 and bi2 are sockets.`Tridirectional(bi,dst,src): Data from bi are copied to dst,
and data from src are copied to bi (i.e. a bidirectional
descriptor is split up into two unidirectional descriptors).
EOF of bi causes that dst is closed. EOF of src causes
that bi is shut down for sending. EOF in both directions
causes that all descriptors are closed. It is required that
bi is a socket.class copier :copy_task -> Unixqueue.event_system ->[unit]engine
copy_task argument.
typesockspec =[ `Sock_inet of Unix.socket_type * Unix.inet_addr * int
| `Sock_inet_byname of Unix.socket_type * string * int
| `Sock_unix of Unix.socket_type * string ]
`Sock_unix(stype,path): Names the Unix domain socket at path.
The socket type stype is an auxiliary piece of information, but
not a distinguishing part of the name. path = "" refers to
anonymous sockets. Otherwise, the path must be an absolute path name.`Sock_inet(stype,addr,port): Names the Internet socket of type
stype bound to the IP address addr and the port.
If stype = Unix.SOCK_STREAM, a TCP socket is meant, and if
stype = Unix.SOCK_DGRAM, a UDP socket is meant. It is allowed
that addr = Unix.inet_addr_any. If port = 0, the name is to
be considered as incomplete.`Sock_inet_byname(stype,name,port): Names the Internet socket of
type stype bound to the IP address corresponding to the
name, and bound to the port. It is unspecified which naming
service is used to resolve name to an IP address, and how it is
used. If the name cannot be resolved, no socket is meant; this
is usually an error. stype is interpreted as for `Sock_inet.
If port = 0, the name is to be considered as incomplete.typeconnect_address =[ `Command of string * (int -> Unixqueue.event_system -> unit)
| `Socket of sockspec * connect_options ]
`Socket(addr,opts): Connect to the passed socket address`Command(cmd,handler): The cmd is started with the shell,
and stdin and stdout are used to transfer data to the
process and from the process, respectively. Only SOCK_STREAM
type is supported. Note that the passed file descriptors are
normal pipes, not sockets (so the descriptors can be individually
closed).
There is not any kind of error detection, so the command should
be failsafe. stderr of the command is connected with stderr of
the caller process.
No provisions are taken to wait for the process; this is the
task of the caller. After the process has been started, the
handler is invoked with the process ID and the event system
to give the caller a chance to arrange that the process will be
waited for.
type connect_options = {
|
conn_bind : |
(* | Bind the connecting socket to this address (same family as the
connected socket required). | *) |
val default_connect_options : connect_optionstypeconnect_status =[ `Command of Unix.file_descr * int
| `Socket of Unix.file_descr * sockspec ]
Uq_engines.connect_address: An engine
connecting with an address `X will return a status of `X.
`Socket(fd,addr): fd is the client socket connected with the
service. addr is the socket address of the client that must be
used by the server to reach the client.`Command(fd, pid): fd is the Unix domain socket connected with
the running command. pid is the process ID.val client_socket : connect_status -> Unix.file_descrconnect_statustypelisten_address =[ `Socket of sockspec * listen_options ]
`Socket(addr,opts): It is listened on a socket with address addrtype listen_options = {
|
lstn_backlog : |
(* | The length of the queue of not yet accepted
connections. | *) |
|
lstn_reuseaddr : |
(* | Whether to allow that the address can be
immediately reused after the previous listener
has its socket shut down | *) |
val default_listen_options : listen_optionsclass type client_socket_connector =object..end
class type server_socket_acceptor =object..end
class type server_socket_listener =object..end
val connector : ?proxy:#client_socket_connector ->
connect_address ->
Unixqueue.event_system -> connect_status engineconnect_address,
optionally using the proxy, and changes to the state
`Done(status) when the connection is established.
If the proxy does not support the connect_address, the class
will raise Addressing_method_not_supported.
The descriptor fd (part of the connect_status) is in non-blocking mode,
and the close-on-exec flag is set.
It is the task of the caller to close this descriptor.
The engine attaches automatically to the event system, and detaches when it is possible to do so. This depends on the type of the connection method. For direct socket connections, the engine can often detach immediately when the conection is established. For proxy connections it is required that the engine copies data to and from the file descriptor. In this case, the engine detaches when the file descriptor is closed.
It is possible that name service queries block execution.
val listener : ?proxy:#server_socket_listener ->
listen_address ->
Unixqueue.event_system -> server_socket_acceptor enginelisten_address.
If passed, the proxy is used to create the server socket.
On success, the engine goes to state `Done acc, where acc is
the acceptor object (see above). The acceptor object can be used
to accept incoming connections.
typedatagram_type =[ `Inet_udp | `Unix_dgram ]
`Unix_dgram: Datagrams over Unix domain sockets`Inet_udp: Internet UDP protocolclass type wrapped_datagram_socket =object..end
wrapped_datagram_socket allows datagrams to be sent via proxies.
class type datagram_socket_provider =object..end
wrapped_datagram_socket objects.
val datagram_provider : ?proxy:#datagram_socket_provider ->
datagram_type ->
Unixqueue.event_system ->
wrapped_datagram_socket enginedatagram_type,
optionally using proxy for sending and receiving datagrams.
The socket is unconnected.
The socket is in non-blocking mode, and the close-on-exec flag is
set.