# Module Cf_state_gadget

    module Cf_state_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 "process" monad type, and a scheduler handles the calls and jumps between multiple simultaneous processes communicating with one another over a very lightweight message passing abstraction called a "wire".

The abstract process 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, as are briefly sumamrized as follows:

- start: launch a new process 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.
- load: load the current process state.
- store: store a new value of the process state.
- 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.

Each process contains an encapsulated state, initialized to a value when the process is started. As a process receives and transmits messages, it can easily manipulate this encapsulated state. When a process has no more messages to receive or transmit, the scheduler reclaims its resources and the final state is discarded.

Any process may read from the internal input stream or write to the external output stream. Conventionally, it is often simpler to define a a reader process and a writer process 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 ('s, 'i, 'o) work

An functionally compositional unit of work in a gadget. It encapsulates the state-continuation monad for a work loop.

    type ('s, 'i, 'o) gate

A gate for receiving messages in a process of type `('s, 'i, 'o) work` 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 `('s, 'i, 'o) work` continuation.

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

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

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

A continuation monad parameterized by process type.

Functions

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

Use `eval y s` to obtain a new flow by evaluating the gadget monad `y` with a state initializer of `a`.

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

Bind the result of `start y s` to start a new process evaluating the gadget `y` with a state initializer `s`.

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

Use `guard m` to receive the next message guarded by `m`. Control will pass to the continuation of the first gate in the guard to receive a message. If no gates in the guard are able to receive a message, i.e. the guard is either empty or all of the gates are on wires that have no transmitters anymore, then control is returned to the scheduler.

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

Use `abort` to abort processing and return to the scheduler. Control will not be passed to any continuation bound to the result.

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

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

    val wirepair : ('s, '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 : ('x, 'i, 'o) wire

Use `null` to construct a `rx` object that produces gates that never receive any messages, and a `tx` object that discards every message transmitted without deliver it. This object can be useful for default arguments to some gadget functions.

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

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

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

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

    val load : ('s, 'i, 'o, 's) t

Bind `load` to get the current state encapsulated in the process.

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

Bind the result of `store obj` to store the state `obj` as the encapsulated state for the current monad.

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

Bind the result of `modify f` to apply `f` to the current encapsulated state of the process and store the resulting new state.

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 simplex : ('s, 'i, 'o,
            ('x, 'i, 'o) rx * ('x, 'i, 'o) tx)
           t

Use `simplex` to construct a new maching pair of `rx` and `tx` objects.

    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.

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

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

Use `duplex` to construct a new duplex communication channel, composed of two wires each in opposite flow. A matching head and tail of the channel is returned.

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

Use `wrap rx tx w` to start a new process 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).