Handle for one spawned asynchronous context. A Context supports validity checks, completion checks, cancellation requests, waiting, and output retrieval. Contexts are cooperatively scheduled: a spawned body runs only while the current context yields, waits, sleeps or blocks, so done? right after spawn is FALSE.


Handle and completion model


makeContext (in Out -- context)

Constructs and schedules one Context from a callable and its declared output schema.


Methods

INIT

(--) Creates an invalid handle.

valid?

(-- valid) Reports whether the handle currently refers to one context.

done?

(-- done) Reports whether the referenced context has finished and stored its completion state.

Preconditions

  • The handle is valid.

cancel

(--) Marks an uncanceled target as canceled and invokes its current cancellation callback synchronously; it does not wait for completion.

Preconditions

  • The handle is valid and is reached through a mutable view, as in @context.cancel.

On Linux, canceling a target suspended in yield, including a sleep whose duration truncates to zero whole nanoseconds, terminates with invalid cancelation function, exit 2. Cancellation propagated through wait or get has the same restriction. Use a timed wait with a nonzero converted duration when cancellation is required.

wait

(--) Waits until the referenced context finishes.

Preconditions

  • The handle is valid and is reached through a mutable view, as in @context.wait.
  • The current context is not waiting on itself.
  • No other unfinished wait or get is already using the same unfinished target context.

get

(-- output) Waits until the referenced context finishes and returns its stored output according to the declared output schema.

Preconditions

  • The handle is valid and is reached through a mutable view, as in @context.get.
  • The current context is not waiting on itself.
  • No other unfinished wait or get is already using the same unfinished target context.

Output mapping

Known issue: A Context that stores a borrowed Ref retains its target address without copying and destroys and reinitializes that target on destruction, even with an In-place output descriptor; return an owned value, such as target new through an immutable view, instead.


Waiting and cancellation semantics


Examples

Initial state

"control"      use
"sync/Context" use

{} Int32 {} [
  context: () Context;
  context.valid? printStack _:;
  0
] "main" exportFunction

Expected Output During Compilation

FALSE

done? and get

"String"       use
"control"      use
"sync/Context" use
"sync/sync"    use

{} Int32 {} [
  context: [2] Int32 spawn;
  context.done? [
    ("done" LF) printList
  ] [
    ("waiting" LF) printList
  ] if
  yield
  context.done? [
    ("done" LF) printList
  ] [
    ("waiting" LF) printList
  ] if
  value: @context.get;
  value isRef [
    ("ref" LF) printList
  ] [
    ("not-ref" LF) printList
  ] if
  drop
  ("value=" @value new LF) printList
  0
] "main" exportFunction

Expected Output

waiting
done
ref
value=2

Cancellation request and get

"String"       use
"control"      use
"sync/Context" use
"sync/sync"    use

{} Int32 {} [
  context: [10.0r64 sleepFor canceled?] FALSE spawn;
  @context.cancel
  result: @context.get;
  (result LF) printList
  0
] "main" exportFunction

Expected Output

TRUE

See also