isolate.channel
import isolate.channel
isolatelifts part of this module out to its own top level; each name below is shown with the path that reaches it. Anything still spelledisolate.channel.*needsimport isolate.channel.
Thread-safe, multi-producer multi-consumer (MPMC) communication queues for passing values and messages across isolate isolates.
Overview
Channels provide synchronized, data-race-free message passing between
concurrent isolate isolates. Because Zuri isolates execute within
isolated heaps, sending a value over a Channel deep-copies the object
graph across the boundary barrier, preserving internal references and
graph topologies without sharing mutable memory.
Channel handles are re-exported by the isolate module, making them
accessible directly via isolate.Channel or isolate.channel().
Channel Types & Backpressure
- Unbounded Channels (
capacity: 0ornil): Messages are enqueued without blockingsend(). The queue dynamically grows as needed. - Bounded Channels (capacity: n > 0): The channel holds at mostnunread messages. Callingsend()when the queue is full blocks the sending isolate until a consumer callsrecv(), providing automatic backpressure to prevent producer tasks from exhausting system memory.
Channel Lifecycle
- Sending:
Channel.send(val, timeout)pushes a value into the channel. If the channel is bounded and full, the call blocks until capacity is available ortimeoutelapses. - Receiving:Channel.recv(timeout)blocks until a value arrives. If the channel is closed and all queued items have been drained,recv()returnsnil. - Non-blocking Peek:Channel.try_recv()retrieves the next value immediately without blocking, returningnilif the channel is currently empty. - Closing:Channel.close()shuts down the channel for subsequent sends. Messages already in the queue remain readable until drained. Subsequent calls tosend()on a closed channel raise aIsolateError.
Multiplexing with select()
The select() function allows an isolate to wait on multiple channels
simultaneously. It blocks until at least one channel is ready to deliver
a value (or is closed), returning a pair [ready_channel, value].
Examples
1. Producer-Consumer Pipeline
import isolate
var ch = isolate.channel(10) # bounded channel with capacity 10
def producer(out_ch) {
iter var i = 1; i <= 5; i++ {
out_ch.send("item-${i}")
}
out_ch.close()
}
var producer_task = isolate.spawn(producer, ch)
while true {
var msg = ch.recv()
if msg == nil {
break # the channel is closed and empty
}
echo "Received: ${msg}"
}
producer_task.join()
2. Fan-Out / Fan-In Isolate Pool
import isolate
var results = isolate.channel()
def isolate_job(isolate_id, count, out_ch) {
iter var i = 1; i <= count; i++ {
out_ch.send("isolate-${isolate_id}-result-${i}")
}
}
var w1 = isolate.spawn(isolate_job, 1, 3, results)
var w2 = isolate.spawn(isolate_job, 2, 3, results)
iter var i = 0; i < 6; i++ {
echo results.recv()
}
w1.join()
w2.join()
3. Multiplexing Channels with select()
import isolate
var ch1 = isolate.channel()
var ch2 = isolate.channel()
isolate.spawn(@(c) { c.send("from ch1") }, ch1)
isolate.spawn(@(c) { c.send("from ch2") }, ch2)
iter var i = 0; i < 2; i++ {
var result = isolate.select([ch1, ch2], 1.0)
var ready_ch = result[0]
var value = result[1]
echo "Got: ${value}"
}
Functions
channel()
isolate.channel(capacity: ?int) -> Channel
Creates a new thread-safe Channel.
import isolate
var unbounded = isolate.channel()
var bounded = isolate.channel(50)
Parameters
capacity(?int) — Maximum buffered messages.nilor0means unbounded.
Returns Channel
select()
isolate.select(channels: list, timeout: ?number)
Multiplexes across multiple channels, blocking until at least one channel is ready to deliver a value or is closed.
The ready value is consumed from the selected channel exactly as if
recv() were called on it directly.
If multiple channels are ready simultaneously, ties are resolved in
favor of the channel with the lower index in channels.
import isolate
var ch1 = isolate.channel()
var ch2 = isolate.channel()
var res = isolate.select([ch1, ch2], 1.5)
var active_ch = res[0]
var msg = res[1]
echo "Received ${msg} from channel"
Parameters
channels(list) — A non-empty list ofChannelinstances.timeout(?number) — Maximum seconds to wait before timing out. Waits indefinitely if omitted ornil.
Returns — list: A two-element list [ready_channel, value], where
value is the message received (nil if the channel was closed and
drained).
Raises ValueError if channels is empty.
Raises IsolateTimeoutError if timeout seconds elapse before any
channel is ready.
Raises IsolateCancelledError if the calling isolate is cancelled
while blocked.
Classes
Channel
class isolate.Channel
A thread-safe, multi-producer multi-consumer (MPMC) message queue.
Constructor
isolate.Channel(capacity: ?int)
Constructs a new Channel with the specified capacity limit.
import isolate
var unbounded = isolate.channel()
var bounded = isolate.channel(100)
Parameters
capacity(?int) — Maximum number of buffered items beforesend()blocks for backpressure.nilor0creates an unbounded channel.
Raises ValueError if capacity is negative.
Channel.send()
isolate.Channel.send(value, timeout: ?number)
Sends value into the channel.
If the channel is bounded and currently full, this call blocks the calling isolate until space becomes available, the timeout elapses, or the caller is cancelled.
ch.send("data payload")
ch.send(42, 0.5) # wait at most 500ms
Parameters
value(any) — The value or object graph to send.timeout(?number) — Maximum seconds to wait before timing out. Waits indefinitely if omitted ornil.
Raises IsolateError if the channel has been closed.
Raises IsolateTimeoutError if timeout seconds elapse before
space is available.
Raises IsolateCancelledError if the calling isolate is cancelled
while blocked.
Channel.recv()
isolate.Channel.recv(timeout: ?number)
Blocks until a message is available and retrieves it.
If the channel is closed and all buffered messages have been received,
recv() returns nil.
var item = ch.recv()
var timed_item = ch.recv(2.0)
Parameters
timeout(?number) — Maximum seconds to wait for a message. Waits indefinitely if omitted ornil.
Returns — any: The received value, or nil if the channel is closed
and empty.
Raises IsolateTimeoutError if timeout seconds elapse before a
value is received.
Raises IsolateCancelledError if the calling isolate is cancelled
while blocked.
Channel.try_recv()
isolate.Channel.try_recv()
Attempts to receive a value without blocking.
var item = ch.try_recv()
if item != nil {
echo "Processed: ${item}"
}
Returns — any: The next available message, or nil if the channel
is currently empty or closed.
Channel.close()
isolate.Channel.close()
Closes the channel.
Buffered messages remain available for consumers to read via recv() or
try_recv(). Calling send() after closing raises IsolateError.
ch.close()
Channel.is_closed()
isolate.Channel.is_closed()
Checks whether the channel has been closed.
if !ch.is_closed() {
ch.send("active")
}
Returns — bool: true if the channel is closed, false otherwise.
Channel.length()
isolate.Channel.length()
Returns the current number of buffered, unread messages in the channel.
var pending = ch.length()
Returns — int: Number of queued items.
Channel.handle()
isolate.Channel.handle()
Returns the underlying native channel pointer.
Used internally by select(). Not intended for direct application
usage.
2026, Richard Ore and Zuri contributors