schan
session-typed channel wrappers over a linear opaque handle.
Since: S1
SSend
(SSend [T R] :int))
protocol step: send a value of type T, then continue as R.
SRecv
(SRecv [T R] :int))
protocol step: receive a value of type T, then continue as R.
SClose
(SClose)
protocol terminus: the channel is closed.
SChan
(SChan [P] :ptr<void>)
a linear channel handle carrying a protocol phantom P.
Since: S1
schan-new
(schan-new [P])
open a session-typed channel running protocol P.
| cap | ring-buffer capacity (>= 1) |
A fresh SChan<P>. The protocol P is fixed by the call site's expected type (or an ascription).
(:: (schan-new 4) (SChan (SSend int SClose))) ; => SChan<SSend int SClose>
Since: S1
schan-send
(schan-send [T R])
send a T over a channel whose protocol begins with SSend T R.
| c | channel at protocol SSend<T R> (consumed) | |
| v | the value to send |
The same channel, advanced to protocol R.
(let [c2 (schan-send c 42)] ...) ; c : SChan<SSend int R> => c2 : SChan<R>
Since: S1
schan-recv
(schan-recv [T R])
receive a T from a channel whose protocol begins with SRecv T R.
| c | channel at protocol SRecv<T R> (consumed) | |
| cell | a cell (from schan-cell-new) that receives the value |
The channel advanced to protocol R. The received value is written into `cell`; read it with schan-cell-get and ascribe to T. NOTE: the plan's ideal signature is `Pair<T SChan<R>>` -- value and continuation returned together as a typed pair. That is currently blocked by a monomorphizer limitation: a generic function cannot return a parametric aggregate (Pair, or any struct) whose element type is a phantom type parameter carried only inside an opaque argument -- the type variable is not recoverable from the opaque, so the aggregate result never specializes and the generic carrier fallback miscompiles (see docs/reported/generic-struct-opaque-element-miscompile.md). Returning the continuation as a bare opaque (SChan R) keeps it *fully typed* -- the protocol-ordering guarantee is intact on every step -- and the value rides out through the cell.
(let [cell (schan-cell-new)
c2 (schan-recv c cell) ; c : SChan<SRecv int R> => c2 : SChan<R>
v (schan-cell-get cell)] ; : int
...)
Since: S1
schan-close
(schan-close [c : (SChan SClose)] :)
close a channel whose protocol has reached SClose.
| c | channel at protocol SClose (consumed) |
nil. The underlying channel is freed.
(schan-close c) ; c : SChan<SClose>
Since: S1
schan-cell-new
(schan-cell-new :)
allocate a one-slot cell for receiving a value.
A fresh cell handle to pass to schan-recv; read it with schan-cell-get and release it with schan-cell-free.
(let [cell (schan-cell-new)] ...)
Since: S1
schan-cell-get
(schan-cell-get [cell ptr<void>] :)
read the value most recently stored into a cell by recv.
| cell | a cell handle from schan-cell-new |
The int64-carried value; ascribe it to the protocol payload type, e.g. (:: (schan-cell-get cell) :Bool).
(schan-cell-get cell) ; => last received value
Since: S1
schan-cell-free
(schan-cell-free [cell ptr<void>] :)
release a cell allocated by schan-cell-new.
| cell | a cell handle from schan-cell-new |
nil.
(schan-cell-free cell)
Since: S1