eve.rt.channel

Cross-thread and cross-fiber communication channels.

This module provides typed channels for safe message passing between concurrent execution contexts. Channels support both bounded (with a maximum capacity) and unbounded operation modes.

Warning: This module contains blocking operations (blockingSend, blockingReceive) that use mutex-based waiting. Never call blocking operations from an event-loop thread — they will block the entire loop and cause deadlocks or latency spikes.

For event-loop-safe usage, use the non-blocking variants:

  • trySend — fails immediately with WOULD_BLOCK if full
  • tryReceive — fails immediately with WOULD_BLOCK if empty

Example (correct usage from worker thread):

// Worker thread — blocking is OK here
auto ch = channel!int(10);
ch.blockingSend(42);  // Blocks until space available

// Event loop thread — use non-blocking only!
auto outcome = ch.trySend(value);
if (!outcome.ok() && outcome.error().reason == ChannelErrorReason.WOULD_BLOCK) {
    // Handle backpressure without blocking the loop
}

Types 5

enumChannelErrorReason : ubyte

Reason a channel operation failed.

UNSPECIFIED = 0Not a real domain error; the default-constructed payload value.
WOULD_BLOCKChannel is empty (for receive) or full (for send).
CLOSEDChannel has been closed.

Recoverable failure of a channel operation.

Fields
ChannelErrorReason reasonWhy the operation failed.
int errnoReserved; OS errors do not apply to channel operations.
structChannel(T)

A bounded channel for cross-thread message passing.

Important: Channels have both blocking and non-blocking operations:

  • blockingSend / blockingReceive — block the thread, unsafe for event loops
  • trySend / tryReceive — return immediately, safe for event loops

Example (non-blocking, event-loop safe):

auto ch = channel!int(10);  // bounded channel with capacity 10

// Non-blocking send (safe from event loop)
if (ch.trySend(42).ok()) {
    writeln("Sent!");
}

// Non-blocking receive (safe from event loop)
auto received = ch.tryReceive();
if (received.ok()) {
    writeln("Received: ", received.value());
}

Example (blocking, worker thread only):

// Only use from worker threads, never from event loop!
ch.blockingSend(42);        // Blocks until space available
auto value = ch.blockingReceive();  // Blocks until value available

Fields
private T[] buffer
private size_t head
private size_t tail
private size_t count
private size_t capacity_
private bool closed_
private Mutex mutex
private Condition notEmpty
private Condition notFull
Methods
ChannelStatus blockingSend(T value) @trustedSend a value into the channel, blocking if the channel is full.
ChannelStatus trySend(T value) @trustedTry to send a value without blocking.
ChannelResult!T blockingReceive() @trustedReceive a value from the channel, blocking if empty.
ChannelResult!T tryReceive() @trustedTry to receive a value without blocking.
ChannelStatus trySend(T value, CancelToken token) @trusted
ChannelStatus blockingSend(T value, CancelToken token) @trusted
void close() @trustedClose the channel, preventing further sends.
bool isClosed() @property @trustedCheck if the channel has been closed.
size_t length() @property @trustedGet the current number of items in the channel.
size_t capacity() @property const pure @safe nothrow @nogcGet the maximum capacity of the channel.
bool empty() @property @trustedCheck if the channel is empty.
Constructors
this(size_t capacity)Construct a bounded channel with the specified capacity.

Functions 1

fnChannel!T * channel(T)(size_t capacity)Create a bounded channel with the specified capacity.