Channels
Calibre provides Channel:<T> for passing values between concurrent tasks.
Note that unlike in Go, Channels in Calibre hold a queue of values.
let mut jobs : Channel:<int> = Channel:<int>.new();let mut results : Channel:<int> = Channel:<int>.new();A channel stores values of a single element type.
The basic operations are sending and receiving.
jobs.send(10);let value := jobs.get();print(value);get() returns an option because a receive may fail or the channel may be empty or closed.
if let .Some : value <- jobs.get() => { print(value);};Channels are especially useful with spawned workers.
const worker := fn (jobs : &Channel:<int>, results : &mut Channel:<int>) => { if let .Some : job <- jobs.get() => { results.send(job * 2); };};The stdlib provides these important channel operations:
Channel.new().send(...).get().try_get().try_send(...).close().closed().recv().try_recv().recv_or(...).send_all(...)
Closing a channel marks it as done.
jobs.close();print(jobs.closed());Channels also work with select, which lets the program react to whichever communication is ready.
select { value <- results => { print(value); }, _ => {}};This makes channels a natural choice for worker pools, pipelines, task queues, and async coordination between spawned tasks.