Events and Channels as in Concurrent ML (extended with communication guards)
See A Concurrent ML Library in Concurrent Haskell by Avik Chaudhuri (email@example.com). The original code as well as the papers can be found at http://www.cs.umd.edu/~Eavik/projects/cmllch/.
User-visible changes to the original code:
- data Channel a
- channel :: IO (Channel a)
- receive :: Channel a -> (a -> Bool) -> Event a
- transmit :: Channel a -> a -> Event ()
- data Event a
- sync :: Event a -> IO a
- choose :: [Event a] -> Event a
- wrap :: Event a -> (a -> IO b) -> Event b
- guard :: IO (Event a) -> Event a
- wrapabort :: IO () -> Event a -> Event a
- spawn :: IO () -> IO ThreadId
Channels transport a single value at a time. The operations on channels are: creation, transmit, and receive. None of them block the calling thread, in fact transmit and receive are pure functions, not IO actions. Blocking may occur only when a thread explicitly synchronizes on the resulting event.
Receive a message from a channel.
receive c cond returns an event that, on synchronization,
accepts a message
m on channel
c and returns
m. The resulting
event is eligible for synchronization with a
transmit c m only if
Transmit a message over a channel.
transmit c m returns an event that, on synchronization,
sends the message
m on channel
c and returns
(). Such an event must
Events encapsulate a potentially blocking point of synchronization between threads, together with possible pre- and post-synchronization code as well as code that is executed (in a separate thread) when an event is not selected (aborted).
Events return a value on synchronization.
Note that by construction, an event can synchronize at exactly one
commit point, where a message is either sent or accepted on a
channel. This commit point may be selected among several other,
potential commit points. Some code may be run before
synchronization, as specified by
guard functions throughout the
event. Some more code may be run after synchronization, as specified
wrap functions that surround the commit point, and by
functions that do not surround the commit point.
Synchronize an event.
This blocks the calling thread until a matching event is available.
Non-deterministically select an event from a list of events, so that the selected event can be synchronized. The other events in the list are aborted.
Specify a post-synchronization action.
wrap v f returns an event that, on synchronization,
synchronizes the event
v and then runs the action returned by
applied to the result.
Specify a pre-synchronization action.
guard a returns an event that, on synchronization,
synchronizes the event returned by the action
a is run
every time a thread tries to synchronize
Specify a post-synchronization action that is spawned if an event is
not selected by a
wrapabort a v returns an event that, on
synchronization, synchronizes the event
v, and on abortion, spawns a
thread that runs the action
a. Here, if
v itself is of the form
choose vs and one of the events in
vs is selected, then
considered selected, so
a is not spawned.