Channels with ard/async/channel
The ard/async/channel module provides typed channels for communicating between fibers. Channels are currently backed by Go channels and are available on the Go target.
Use channels when one fiber needs to send values to another fiber without sharing mutable state.
use ard/asyncuse ard/async/channeluse ard/io
fn main() { let ch = channel::new<Int>()
let sender = async::start(fn() { ch.send(42) ch.close() })
let value = ch.recv().or(0) sender.join()
io::print(value)}extern type Chan<$T>
Section titled “extern type Chan<$T>”The raw native channel type. Most Ard code should use Channel<$T> instead.
Project FFI functions may use channel::Chan<T> when they need to receive or return a raw Go channel.
use ard/async/channel
extern fn observe(ch: channel::Chan<Int>) Int = "Observe"struct Channel<$T>
Section titled “struct Channel<$T>”A typed channel wrapper.
Fields:
chan: Chan<$T>— the raw native channel.
Most user code creates a channel with channel::new<T>() and then uses the methods below.
fn new<$T>(size: Int?) Channel<$T>
Section titled “fn new<$T>(size: Int?) Channel<$T>”Create a channel for values of type $T.
- If
sizeis omitted ornone, the channel is unbuffered. - If
sizeis positive, the channel is buffered with that capacity. - Non-positive sizes fall back to an unbuffered channel.
use ard/async/channel
let unbuffered = channel::new<Int>()let buffered = channel::new<Str>(size: 10)The type argument is required so the compiler knows what values can move through the channel.
fn send(value: $T) Bool
Section titled “fn send(value: $T) Bool”Send a value to the channel.
Returns true if the send succeeds. Returns false if the channel has already been closed.
let ch = channel::new<Int>(size: 1)let sent = ch.send(7)For unbuffered channels, send blocks until another fiber receives the value.
fn recv() $T?
Section titled “fn recv() $T?”Receive the next value from the channel.
Returns:
some(value)when a value is received.nonewhen the channel is closed and drained.
let ch = channel::new<Int>(size: 1)ch.send(7)ch.close()
let value = ch.recv().or(0) // 7let done = ch.recv().is_none() // truefn close() Bool
Section titled “fn close() Bool”Close the channel.
Returns true if this call closed the channel. Returns false if the channel was already closed.
let ch = channel::new<Int>()let closed = ch.close()let closed_again = ch.close() // falseWorking with fibers
Section titled “Working with fibers”Channels are most useful with ard/async fibers.
use ard/asyncuse ard/async/channeluse ard/io
fn main() { let ch = channel::new<Str>()
let producer = async::start(fn() { ch.send("ready") ch.close() })
match ch.recv() { message => io::print(message), _ => io::print("channel closed"), }
producer.join()}Type safety
Section titled “Type safety”Channels are generic. A Channel<Int> only accepts Int values and recv() returns Int?.
let ints = channel::new<Int>()ints.send(1) // OKints.send("one") // Error: expected IntIf you refer to the Channel type directly, include its type argument:
use ard/async/channel
// If the Ard project is named `demo`, project Go FFI types are qualified// with the generated project package name.extern type RawEvent = "demo.Event"extern fn events() channel::Channel<RawEvent> = "Events"Go FFI notes
Section titled “Go FFI notes”When an Ard extern function is declared as returning channel::Channel<T>, the Go FFI function can return the raw Go channel (chan T). The Go backend wraps that raw channel into Ard’s Channel<T> wrapper before Ard code calls methods like .recv().
use ard/async/channel
// If the Ard project is named `demo`, project Go FFI types are qualified// with the generated project package name.extern type RawEvent = "demo.Event"extern fn events() channel::Channel<RawEvent> = "Events"package ffi
type Event struct{}
func Events() chan Event { return make(chan Event)}Use channel::Chan<T> in Ard extern signatures when you explicitly want the raw native channel type.