Channel
Channel<T> is the primary synchronization primitive for concurrent tasks in Chuks. Channels are typed — the element type is fixed at construction and enforced by the type checker on every send and receive.
Import
Section titled “Import”import { Channel } from "std/channel";Creating a channel
Section titled “Creating a channel”Channel<T> is a generic class. The type parameter <T> is required — every channel carries values of a single concrete type.
// Buffered channel of ints — can hold up to 5 values before send blocksconst numbers: Channel<int> = new Channel<int>(5);
// Unbuffered channel of strings — send blocks until a receiver is readyconst messages: Channel<string> = new Channel<string>(0);Sending and receiving
Section titled “Sending and receiving”send(value: T): void
Section titled “send(value: T): void”Sends a value into the channel. Blocks if the buffer is full (or the channel is unbuffered and no receiver is ready).
numbers.send(42);// numbers.send("hi"); // ❌ type error — Channel<int>receive(): T?
Section titled “receive(): T?”Receives a value from the channel. Blocks until a value is available. Returns null once the channel is closed and drained.
var v: int? = numbers.receive();if (v != null) { println("got: " + string(v));}The result is T? (nullable) so you can detect channel closure with a simple null check.
close(): void
Section titled “close(): void”Closes the channel. No more values can be sent. Receivers can still drain any buffered values; once the channel is empty, receive() returns null.
numbers.close();Non-blocking operations
Section titled “Non-blocking operations”tryReceive(): { value: T?, ok: bool }
Section titled “tryReceive(): { value: T?, ok: bool }”Attempts to receive without blocking. Returns a map with two fields:
ok: true— a value was available;valueis the receivedT?.ok: false— the channel was empty (a blocking receive would have waited).
const result = numbers.tryReceive();if (result["ok"]) { println("got: " + string(result["value"]));} else { println("nothing yet");}trySend(value: T): bool
Section titled “trySend(value: T): bool”Attempts to send without blocking. Returns true if the value was queued, false if the buffer is full.
const sent: bool = numbers.trySend(99);if (!sent) { println("buffer full, dropping");}Iterating until closed
Section titled “Iterating until closed”The idiomatic pattern for draining a channel is a for loop driven by receive():
for ( var v: int? = numbers.receive(); v != null; v = numbers.receive()) { println(v);}This loop exits cleanly once the producer calls numbers.close() and the buffer is drained.
Producer / consumer example
Section titled “Producer / consumer example”import { Channel } from "std/channel";
function main() { const ch: Channel<int> = new Channel<int>(0); // unbuffered
spawn produce(ch);
for ( var v: int? = ch.receive(); v != null; v = ch.receive() ) { println(v); } println("done");}
function produce(ch: Channel<int>): void { for (var i = 0; i < 5; i++) { ch.send(i); } ch.close();}Output:
01234doneFor a full worker-pool walkthrough — fanning jobs out to multiple workers and collecting results — see the Worker Pool with Channels tutorial.
API reference
Section titled “API reference”| Member | Type | Description |
|---|---|---|
new Channel<T>(bufferSize) | constructor | Create a channel of T with the given buffer size. |
send(value: T) | void | Send a value (blocks if buffer is full). |
receive() | T? | Receive a value (blocks if empty); null on close. |
close() | void | Close the channel. |
tryReceive() | { value: T?, ok: bool } | Non-blocking receive. |
trySend(value: T) | bool | Non-blocking send. |