Producer-Consumer
The producer-consumer pattern decouples data generation from processing. The bounded channel (capacity 3) provides natural backpressure: the producer blocks when the buffer is full.
Code
// Producer-consumer pattern with bounded channel
// Patrón productor-consumidor con canal acotado
var items_ch: Map = Map.new()
fn produce() -> int {
var i: int = 0
while i < 5 {
let item: int = (i + 1) * 10
print("produced: " + int_to_string(item))
channel_send(items_ch, item)
i = i + 1
}
channel_send(items_ch, -1)
return 0
}
fn consume() -> int {
while true {
let item: int = channel_recv(items_ch)
if item < 0 { return 0 }
print("consumed: " + int_to_string(item))
}
return 0
}
fn main() -> int {
// Bounded channel — producer blocks if buffer is full
items_ch = channel_new(3)
let p: int = thread_spawn(produce)
let c: int = thread_spawn(consume)
thread_join(p)
thread_join(c)
channel_destroy(items_ch)
print("pipeline complete")
return 0
}
Output
produced: 10 produced: 20 produced: 30 produced: 40 produced: 50 consumed: 10 consumed: 20 consumed: 30 consumed: 40 consumed: 50 pipeline complete
Explanation
The channel items_ch has a capacity of 3, meaning the producer can send at most 3 items before blocking. This provides natural backpressure -- if the consumer is slow, the producer automatically slows down to match.
The producer generates values 10, 20, 30, 40, 50 and sends them through the channel, followed by a -1 sentinel to signal completion. The consumer loops on channel_recv, processing each item until it sees the sentinel.
The exact interleaving of "produced" and "consumed" messages depends on scheduling, but the order within each stream is always preserved. The bounded buffer prevents the producer from overwhelming the consumer with data.