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 — returns immediately with WOULD_BLOCK if full
  • tryReceive — returns 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!
if (ch.trySend(value) == ChannelStatus.WOULD_BLOCK) {
    // Handle backpressure without blocking the loop
}

Types 2

enumChannelStatus : ubyte

Channel status codes returned by non-blocking operations.

Retryability and Fatality Guide:

  • OK — Success, no retry needed
  • WOULD_BLOCK — Retryable after data is available or space is freed
  • CLOSED — Fatal, channel cannot be reused

OK = 0Operation completed successfully. Retryable: No (operation completed) Fatal: No
WOULD_BLOCK = 1Channel is empty (for receive) or full (for send). Retryable: Yes (for send: after space is freed; for receive: after data is available) Fatal: No Action: Wait for channel state to change before re...
CLOSED = 2Channel has been closed. Retryable: No Fatal: Yes (channel cannot be reused)
structChannel(T)

A typed channel for cross-thread/cross-fiber communication.

Channels provide a safe way to pass messages between concurrent execution contexts. They can be bounded (with a maximum capacity) or unbounded.

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) == ChannelStatus.OK) {
    writeln("Sent!");
}

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

Example (blocking, worker thread only):

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

Fields
T[] buffer
size_t head
size_t tail
size_t count
size_t capacity_
bool closed_
Mutex mutex
Condition notEmpty
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.
ChannelStatus blockingReceive(out T value) @trustedReceive a value from the channel, blocking if empty.
ChannelStatus tryReceive(out T value) @trustedTry to receive a value without blocking.
ChannelStatus trySend(T value, CancelToken token) @trusted
ChannelStatus tryReceive(out T value, CancelToken token) @trusted
ChannelStatus blockingSend(T value, CancelToken token) @trusted
ChannelStatus blockingReceive(out 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.