# Module Cf_gadget

    module Cf_gadget: sig .. end

Monadic composition of complex stream processors. An experimental interface for constructing interactive functional systems in a single thread of control.

###### Overview

This module implements a marginally more general version of the Gadget system described in Chapter 30 of Magnus Carlsson's and Thomas Hallgren's joint Ph.D. thesis.

In the context of this module, a "gadget" is a monad that evaluates into a `Cf_flow` object, capable of alternately reading from a source of input values and writing to a sink of output values. The continuation monad is specialized over an abstract "work" monad type, and a scheduler handles the calls and jumps between multiple simultaneous work units, communicating with one another over a very lightweight message passing abstraction called a "wire".

The abstract work monad is a kind of state-continuation monad for operations over the internal `Cf_flow` value. The operations it supports are lifted into the gadget monad, and they are summarized as follows:

- start: launch a new gadget in the scheduler.
- wire: create a new message wire.
- put: send a message on a wire.
- get: create a gate for receiving messages on a wire.
- guard: receive a message from one of several gates.
- read: read a new value from the external input.
- write: write a new value to the external output.

A wire is logically composed of a receiver and a transmitter, with weak mutual references between them. When either end of the wire is reclaimed by the memory allocator, the other end is automatically rendered into a null wire, i.e. receivers never get messages and transmitters put messages by discarding them.

A pair of classes are provided to represent the receiver and the transmitter on a wire. Objects of the `rx` class define a `get` method for creating a "gate" that can receive a message. Objects of the `tx` class define a `put` method for transmitting a message. Both objects can be constructed with a wire object, and a convenience operators are defined for creating a new wire and construction a pair of associated `rx` and `tx` objects.

Any gadget may read from the internal input stream or write to the external output stream. Conventionally, it is often simpler to define a a reader gadget and a writer gadget to localize these effects.

Note: see Magnus Carlsson's and Thomas Hallgren's joint Ph.D. thesis for a complete dissertation on the nature of the system of concepts behind this module.

###### Overview

This module implements a marginally more general version of the Gadget system described in Chapter 30 of Magnus Carlsson's and Thomas Hallgren's joint Ph.D. thesis.

In the context of this module, a "gadget" is a monad that evaluates into a `Cf_flow` object, capable of alternately reading from a source of input values and writing to a sink of output values. The continuation monad is specialized over an abstract "work" monad type, and a scheduler handles the calls and jumps between multiple simultaneous work units, communicating with one another over a very lightweight message passing abstraction called a "wire".

The abstract work monad is a kind of state-continuation monad for operations over the internal `Cf_flow` value. The operations it supports are lifted into the gadget monad, and they are summarized as follows:

- start: launch a new gadget in the scheduler.
- wire: create a new message wire.
- put: send a message on a wire.
- get: create a gate for receiving messages on a wire.
- guard: receive a message from one of several gates.
- read: read a new value from the external input.
- write: write a new value to the external output.

A wire is logically composed of a receiver and a transmitter, with weak mutual references between them. When either end of the wire is reclaimed by the memory allocator, the other end is automatically rendered into a null wire, i.e. receivers never get messages and transmitters put messages by discarding them.

A pair of classes are provided to represent the receiver and the transmitter on a wire. Objects of the `rx` class define a `get` method for creating a "gate" that can receive a message. Objects of the `tx` class define a `put` method for transmitting a message. Both objects can be constructed with a wire object, and a convenience operators are defined for creating a new wire and construction a pair of associated `rx` and `tx` objects.

Any gadget may read from the internal input stream or write to the external output stream. Conventionally, it is often simpler to define a a reader gadget and a writer gadget to localize these effects.

Note: see Magnus Carlsson's and Thomas Hallgren's joint Ph.D. thesis for a complete dissertation on the nature of the system of concepts behind this module.

###### Types

    type ('i, 'o) work

An functionally compositional work unit in a gadget, encapsulating the state-continuation monad for the underlying `Cf_flow` object.

    type ('i, 'o) gate

A gating sequence for receiving messages using the `guard` function.

    type ('x, 'i, 'o) wire

An object capable of delivering messages of type `'x` from a sender to a a receiver in a `('i, 'o) work` continuation.

    type ('i, 'o, 'a) guard = (('i, 'o) gate, 'a) Cf_cmonad.t

A guard for receiving a message from one or more sources.

    type ('i, 'o, 'a) t = (('i, 'o) work, 'a) Cf_cmonad.t

A continuation monad parameterized by work unit type.

###### Functions

    val eval : ('i, 'o, unit) t -> ('i, 'o) Cf_flow.t

Use `eval y` to obtain a new flow by evaluating the gadget monad `y`.

    val start : ('i, 'o, unit) t -> ('i, 'o, unit) t

Use `start y` to start a new gadget evaluating the gadget `y`.

    val guard : ('i, 'o, unit) guard -> ('i, 'o, 'a) t

Use `guard m` to receive the next message guarded by `m`. The continuation bound to the result is discarded and control passes to the scheduler.

    val abort : ('i, 'o, 'a) t

Use `abort` to abort gadgeting and return to the scheduler. This is a convenient shortcut for `guard Cf_cmonad.nil`.

    val wire : ('i, 'o, ('x, 'i, 'o) wire) t

Use `wire` to return a new wire for carrying messages of type `'x`.

    val wirepair : ('i, 'o, ('x, 'i, 'o) wire * ('y, 'i, 'o) wire)
           t

Use `wirepair` to return a pair of new wires for carrying messages of type `'x` and `'y`.

    val null : ('i, 'o, ('x, 'i, 'o) wire) t

Use `null` to construct a wire that discards every message transmitted without ever delivering it. Such wires can be useful for default arguments to some gadget functions.

    val read : ('i, 'o, 'i) t

Bind `read` to get the next input value from the external stream.

    val write : 'o -> ('i, 'o, unit) t

Bind the result of `write obj` to put the next output value into the external stream.

###### Classes

    class type connector = object .. end

The class type of connector objects.

    class [['x, 'i, 'o]] rx : ('x, 'i, 'o) wire -> object .. end

The class of receiver objects.

    class [['x, 'i, 'o]] tx : ('x, 'i, 'o) wire -> object .. end

The class of transmitter objects.

###### Miscellaneous

    val connect : ('i, 'o, ('x, 'i, 'o) wire) t ->
           ('i, 'o, ('x, 'i, 'o) rx * ('x, 'i, 'o) tx) t

Use `connect m` to construct a new matching pair of `rx` and `tx` objects from the wire returned by `m`.

    val simplex : ('i, 'o, ('x, 'i, 'o) rx * ('x, 'i, 'o) tx) t

Use `simplex` to construct a new matching pair of `rx` and `tx` objects. This is a convenient abbreviation of `connect wire`.

    type ('x, 'y, 'i, 'o) pad = ('x, 'i, 'o) rx * ('y, 'i, 'o) tx

A pair of convenience types for representing each end of a bundle of two wires used for duplex communication. By convention, a `pad` comprises a receiver for control events and a transmitter for notification events, and a `fix` comprises the transmitter for control events and the receiver for notification events

    type ('x, 'y, 'i, 'o) fix = ('y, 'i, 'o) rx * ('x, 'i, 'o) tx

    val connectpair : ('i, 'o, ('x, 'i, 'o) wire * ('y, 'i, 'o) wire)
           t ->
           ('i, 'o, ('x, 'y, 'i, 'o) fix * ('x, 'y, 'i, 'o) pad)
           t

Use `connectpair m` to construct a new duplex communication channel, composed with the wire pair returned by `m`. A matching `fix` and `pad` of the channel are returned.

    val duplex : ('i, 'o, ('x, 'y, 'i, 'o) fix * ('x, 'y, 'i, 'o) pad)
           t

Use `duplex` to construct a new duplex communication channel, composed of two wires each in opposite flow. A matching `fix` and `pad` for each channel are returned. This is a convenient abbreviation of `connectpair wirepair`.

    val wrap : ('x, 'i, 'o) #rx ->
           ('y, 'i, 'o) #tx ->
           ('x, 'y) Cf_flow.t -> ('i, 'o, unit) t

Use `wrap rx tx w` to start a new gadget that wraps the flow `w`, so that it reads output from the flow (copying it to `tx` object) and writes input to the flow (copying it from the `rx` object).

    class virtual [['i, 'o]] next : object .. end

Use `inherit ['i, 'o] next` to derive a class that implements an intermediate state in a machine.

    class virtual [['i, 'o]] start : object .. end

Use `inherit ['i, 'o] start` to derive a class to represent the initial state of a machine.

    val create : (('c, 'n, 'i, 'o) pad -> ('i, 'o) #start) ->
           ('i, 'o, ('c, 'n, 'i, 'o) fix) t

Use `create f` to create a duplex channel, and apply `f` to the resulting `pad` to obtain the initial state of a machine. The machine is started and the corresponding `fix` is returned.

    val createM : (('c, 'n, 'i, 'o) pad ->
            ('i, 'o, ('i, 'o) #start) t) ->
           ('i, 'o, ('c, 'n, 'i, 'o) fix) t

Use `createM f` to create a duplex channel, and apply `f` to the resulting `pad` to obtain a continuation monad that evaluates to the initial state of a machine. The machine is started and the corresponding `fix` is returned.