Fibers & Channels
For a conceptual introduction to fibers and channels, see the Language Tour. This page covers the specifics.
gab\fiber
Fibers are created with Fibers.make:, which takes a block and immediately queues it for execution. The fiber may run on any OS thread managed by Gab’s runtime.
Fibers.make () => do
'Hello from a fiber!'.println
end
gab\channel
Channels are created with Channels.make:
ch = Channels.make
Send a value with <!:
ch <! 'hello'
Receive a value with >!:
value = ch >!
In Gab, channels are unbuffered. Practically, this means that Both operations are blocking: a send blocks until a receiver is ready, and a receive blocks until a sender is ready. For this reason, channels serve as both a primitive for sharing data, and way to synchronize fibers.
Note
For a comprehensive example of synchronizing fibers with channels, see the pub/sub broker example.
Buffered channels
While synchronization is useful, it can sometimes be a bottleneck for performance. If producers outpace consumers, then channels may become backed-up as producers have to block and wait for consumers.
In this scenario it is better to use a buffered channel, which can hold up to a certain number of values before producers have to begin blocking.
Lets build this with the primitives Gab gives us!
buffered: .def (Channels, (n) => do
input = Channels.make
output = Channels.make
Ranges.make(0 n).each () => do
# Spawn n fibers to perform buffering.
Fibers.make () => do
# Take out of input channel, and forward it to the output channel.
output <! (input >!)
# Loop by calling self
self.()
end
end
(input, output)
end)
(input, output) = Channels.buffered(10)
The sender writes to input and can race N values ahead before blocking. The consumer reads from output. The N slot fibers sit between them, each capable of holding one value in flight.
Note: operator precedence
<! and >! are operator sends. The . prefix is optional but changes the precedence. Named sends (.name) bind tighter than bare operators.
ch <! value # operator form
ch.>! .println # dot prefix — binds tighter, result chains into .println