Skip to content
Beskid Platform specification

Beskid

Jump to a Beskid service

Beskid

Jump to a Beskid service

Concurrency package - Contracts and edge cases

Platform spec article

Concurrency package - Contracts and edge cases

Spec standingStandard

Owner
Piotr Mikstacki
Submitter
Piotr Mikstacki
  • Channel<T>.Create(options: ChannelOptions = default)default is unbounded.
  • ChannelOptions.Bounded(n)n > 0; Send parks when full (Wait mode).
  • ChannelOptions.Unbounded — equivalent to default; queue grows until OOM (documented risk).
  • ChannelOptions.SingleReader() / SingleWriter() — unbounded factories that set optimization hints without changing queue semantics.
  • Optional capacity field inside options must not contradict Bounded / Unbounded variant; bounded wins when Bounded(n) is chosen.
MethodContract
SendResult<(), ChannelError>; blocks/parks fiber when full (bounded + Wait mode)
ReceiveResult<T, ChannelError>; parks when empty and open
TrySendOption<()>None if would block
TryReceiveOption<T>None if would block
CloseIdempotent writer close; no panic
  • Closed — endpoint closed
  • Cancelled — owning fiber cancelled (Cancel / OnCancelled path)

TrySend / TryReceive use Option only (None = would block); no ChannelError::Full.

  • SingleReader / SingleWriter — optimization hints; behavior unchanged if violated but may enable faster paths
  • BoundedChannelFullMode::Wait — default; sender parks
  • No AllowSynchronousContinuations (async-only .NET concept)

Fiber<T> is a corelib struct (runtime handle) that must declare:

event OnCancelled();

The spawn entry function does not declare OnCancelled — only the handle type does.

MethodContract
JoinResult<T, FiberError>Ok(value), Cancelled, StackOverflow, Panicked
Detachvoid; parent waives Join; child panic aborts process
Cancelvoid; raises OnCancelled on child fiber, then unblocks parked ops with Cancelled

OnCancelled runs on the child fiber. Unhandled failure in a handler aborts the process. Handlers must not Join self, Join an ancestor, or block indefinitely.

Join from a child fiber to a parent (or ancestor) handle is a compile error (JoinWouldDeadlock).

M3 completion requires generated code to import the ABI symbol fiber_spawn_with_cancel_slot, pass the handle’s OnCancelled event slot, and treat the returned handle as an i64 fiber id rather than a pointer.

  • Cancelled
  • StackOverflow
  • Panicked — carries diagnostic handle / message policy per runtime
  • Homogeneous only in v1Hub<T> registers only Channel<T> instances
  • Register(index, channel) / Unregister(index)index is user-chosen i64 key in WaitReceive result
  • WaitReceiveResult<HubReceiveResult, HubError> where HubReceiveResult carries member index and received value
  • Round-robin fairness among ready channels (see decisions record)
  • Multiplexing unlike types: use Channel<HubMessage> (enum/union) or multiple hubs — not mixed-type Hub in v1
  • WaitSendnot in v1
  • Replaces language-level select for v1
  • Mutex.LockResult<MutexGuard, MutexError>
  • Mutex.TryLockOption<MutexGuard> (None if would block)
  • Mutex.Unlock — explicit in v1 (no defer required for spec)
  • WaitGroup.Wait parks until counter zero; Add/Done follow Go semantics

Console.OnResize and control onTick paths must publish into a Channel<T> (or Hub member) so UI fibers Receive events without multicast event invocation across fibers. Language event syntax may remain for single-fiber use; cross-fiber UI must use Channel (see console-terminal-events).