TupleSpace
A Linda-style shared tuple space for concurrent coordination.
TupleSpace stores tuples (any Maggie objects) and retrieves them by matching against CUE templates. Operations can be blocking (in:, read:) or non-blocking (tryIn:, tryRead:). Blocking operations suspend the current process until a matching tuple is available.
Tuples are matched using CUE unification: a template is a CueValue, and a tuple matches if projecting it into CUE and unifying with the template produces no error (no bottom).
Tuples have three modes: - Linear (default): consumed exactly once by in: - Persistent: never consumed; in: returns a copy but keeps the original - Affine: consumed at most once, can expire via TTL
ts := TupleSpace new.
ts isEmpty >>> true
ts out: 42.
ts size >>> 1
ts isEmpty >>> false
Class Methods
primitives
Instance Methods
primitives
uncategorized
Take the first tuple matching the CUE template. Blocks until a matching tuple is available. The tuple is removed from the space (destructive read / linear consumption).
For persistent tuples, the value is returned but the tuple stays in the space (non-destructive).
The template must be a CueValue. Use CueContext>>compileString: to create templates.
| ts <TupleSpace> ctx <CueContext> |
ts := TupleSpace new.
ctx := CueContext new.
[ts out: 42] fork.
ts in: (ctx compileString: 'int') value
Atomically take ALL tuples matching an array of templates. Blocks until all templates are simultaneously satisfiable. Each template must match a DIFFERENT tuple.
This is the tensor product from linear logic -- it prevents the classic coordination bug where an agent takes a task but the required resource was grabbed between two separate in: calls.
Returns an Array of results in the same order as the templates.
| ts <TupleSpace> ctx <CueContext> |
ts := TupleSpace new.
ctx := CueContext new.
ts out: 42.
ts out: 'hello'.
ts inAll: {(ctx compileString: 'int') value. (ctx compileString: 'string') value}
Take whichever tuple matches first from an array of templates. Scans tuples and returns the first match from any template. If none match, blocks until any one does.
This is the additive disjunction from linear logic -- like Channel select: but for tuple templates.
| ts <TupleSpace> ctx <CueContext> |
ts := TupleSpace new.
ctx := CueContext new.
ts out: 42.
ts inAny: {(ctx compileString: 'int') value. (ctx compileString: 'string') value}
Return true if the space contains no tuples.
ts := TupleSpace new.
ts isEmpty >>> true
ts out: 1.
ts isEmpty >>> false
Publish a tuple into the space. Non-blocking. If a process is blocked waiting for a matching tuple (via in: or read:), it will be woken immediately. The tuple is stored in linear mode (consumed exactly once by in:).
ts := TupleSpace new.
ts out: 42.
ts out: 'hello'.
ts size >>> 2
Publish a tuple that is automatically removed when the given CancellationContext is cancelled. The tuple behaves as linear until cancellation.
| ts <TupleSpace> ctx <CancellationContext> |
ts := TupleSpace new.
ctx := CancellationContext withCancel.
ts out: 'resource' withContext: ctx.
ctx cancel.
Publish an affine tuple with a time-to-live in milliseconds. The tuple is automatically removed after the TTL expires if not consumed first. Expired tuples are lazily cleaned during scans.
| ts <TupleSpace> |
ts := TupleSpace new.
ts outAffine: 'ephemeral offer' ttl: 5000.
Publish a persistent tuple into the space. Persistent tuples are never consumed by in: -- reads return the value but the tuple stays in the space. Useful for shared facts and blackboard knowledge.
ts := TupleSpace new.
ctx := CueContext new.
intTmpl := (ctx compileString: 'int') value.
ts outPersistent: 42.
ts tryIn: intTmpl >>> 42
ts size >>> 1
ts tryIn: intTmpl >>> 42
ts size >>> 1
Return a human-readable description.
Read the first tuple matching the CUE template. Blocks until a matching tuple is available. The tuple remains in the space (non-destructive read).
| ts <TupleSpace> ctx <CueContext> |
ts := TupleSpace new.
ctx := CueContext new.
ts out: 42.
ts read: (ctx compileString: 'int') value
Return the number of tuples currently stored.
ts := TupleSpace new.
ts size >>> 0
ts out: 1.
ts out: 2.
ts size >>> 2
Try to take a matching tuple without blocking. Returns the tuple if found (and removes it), or nil if no match.
ts := TupleSpace new.
ctx := CueContext new.
intTmpl := (ctx compileString: 'int') value.
ts tryIn: intTmpl >>> nil
ts out: 42.
ts tryIn: intTmpl >>> 42
ts size >>> 0
Try to read a matching tuple without blocking. Returns the tuple if found (does not remove it), or nil if no match.
ts := TupleSpace new.
ctx := CueContext new.
intTmpl := (ctx compileString: 'int') value.
ts tryRead: intTmpl >>> nil
ts out: 42.
ts tryRead: intTmpl >>> 42
ts size >>> 1