# Class type Uq_engines.multiplex_controller

    class type multiplex_controller = object .. end

A `multiplex_controller` is a quite low-level device to abstract bidirectional socket connections. It is independent of any real device.

There can be a reader, a writer (or both), or alternatively, the shutdown process may be in progress. One cannot have more than one reader and more than more writer.

    method alive : bool

If the controller is alive, the socket is not yet completely down.

    method mem_supported : bool

Whether `start_mem_reading` and `start_mem_writing` are possible

    method event_system : Unixqueue.event_system

Returns the event system

    method reading : bool

True iff there is a reader

    method start_reading : ?peek:(unit -> unit) ->
           when_done:(exn option -> int -> unit) -> string -> int -> int -> unit

Start reading from the connection. When data is available, the `when_done` callback is invoked. The int is the number of read bytes. It is 0 if an error occurred which is indicated by the exception. The exception `End_of_file` is used when the end of the data stream is reached. The exception `Cancelled` indicates that reading has been cancelled in the meantime.

This starts one-time read job only, i.e. it is not restarted after `when_done` has been invoked.

It is an error to start reading several times.

The function `peek` is called immediately before data is read in from the underlying communication channel.

For getting an engine-based version of `start_reading`, use a `signal_engine`:

        let (e, signal) = signal_engine esys in
        mplex # start_reading ~when_done:(fun xo n -> signal (xo,n)) ...

Now `e` will transition to ``Done(x0,n)` when the read is done.

    method start_mem_reading : ?peek:(unit -> unit) ->
           when_done:(exn option -> int -> unit) ->
           Netsys_mem.memory -> int -> int -> unit

Same as `start_reading`, but puts the data into a `memory` buffer. There is an optimization for the case that the descriptor is a connected socket, or supports `Unix.read`. If this is not possible the method raises `Mem_not_supported`.

    method cancel_reading : unit -> unit

Cancels the read job. The `when_done` callback is invoked with the number of bytes read so far (which may be 0) and the exception `Cancelled`.

It is no error if there is no reader.

    method writing : bool

True iff there is a writer

    method start_writing : when_done:(exn option -> int -> unit) -> string -> int -> int -> unit

Start writing to the connection. When data is written, the `when_done` callback is invoked. The int is the number of written bytes. It is 0 if an error occurred which is indicated by the exception. The exception `Cancelled` indicates that writing has been cancelled in the meantime.

This starts one-time write job only, i.e. it is not restarted after `when_done` has been invoked.

It is an error to start writing several times.

See the comment for `start_reading` for how to get an engine-based version of this method.

    method start_mem_writing : when_done:(exn option -> int -> unit) ->
           Netsys_mem.memory -> int -> int -> unit

Same as `start_writing`, but takes the data from a `memory` buffer. There is an optimization for the case that the descriptor is a connected socket, or supports `Unix.write`. If this is not possible the method raises `Mem_not_supported`.

    method supports_half_open_connection : bool

Whether the underlying transport mechanism can close the write side of the connection only (half-open connection).

    method start_writing_eof : when_done:(exn option -> unit) -> unit -> unit

Start writing the EOF marker to the connection. When it is written, the `when_done` callback is invoked. The exception `Cancelled` indicates that writing has been cancelled in the meantime.

This starts one-time write job only, i.e. it is not restarted after `when_done` has been invoked.

It is an error to start writing several times. It is an error to write EOF when the socket does not support half-open connections.

See the comment for `start_reading` for how to get an engine-based version of this method.

    method cancel_writing : unit -> unit

Cancels the write job. The `when_done` callback is invoked with the number of bytes read so far (which may be 0) and the exception `Canelled`.

It is no error if there is no writer.

    method read_eof : bool

Whether the EOF marker has been read

    method wrote_eof : bool

Whether the EOF marker has been written

    method shutting_down : bool

True iff the shutdown is in progress

    method start_shutting_down : ?linger:float -> when_done:(exn option -> unit) -> unit -> unit

Start shutting down the connection. After going through the shutdown procedure, the `when_done` callback is invoked. The exception indicates whether an error happened. `Cancelled` means that the shutdown operation has been cancelled in the meantime.

The underlying file descriptor (if any) is not closed. A shutdown is only a protocol handshake. After a shutdown, both `read_eof` and `wrote_eof` are true. Call `inactivate` to close the descriptor.

Optionally, one can `linger` for a certain period of time. It is only lingered when the EOF was written before the EOF is seen on input. Defaults to `linger 60.0`. Set to 0 to turn off.

See the comment for `start_reading` for how to get an engine-based version of this method.

    method cancel_shutting_down : unit -> unit

Cancels the shutdown procedure. After that, the state of the connection is undefined. The `when_done` callback is invoked with the exception `Cancelled`.

It is no error if no shutdown is in progress.

    method inactivate : unit -> unit

Inactivates the connection immediately, and releases any resources the controller is responsible for (e.g. closes file descriptors). Note that this is more than cancelling all pending operations and shutting the connection down. However, the details of this method are implementation-defined. Callbacks are not invoked.