Standard library · Time and concurrency

chan

A channel for passing values from one thread to another, with a buffer, timeouts and closing.

import chan
On this page
  1. Types

A channel is a queue that several threads send values into at one end and receive from at the other; it handles the locks and the waiting for you. You give the value type when you create it, as in chan.Chan<i64>, and call init with a capacity before using it.

When the buffer is full, send waits; when it is empty, recv does. A channel of capacity zero is "unbuffered": the sender waits until a receiver takes the value. After close, sending returns false but receivers still get the values that are left; once the channel is empty, ok turns false and a receiving loop can end.

Types

Chan

struct Chan<T>
A channel of values of type T.
NameTypeDescription
bufT*The buffer of values.
ctli64*The internal state: the head and tail of the queue, the count and whether it is closed.
capi64 = 0The capacity.
zidxi64 = 0The buffer slot holding the type's zero value, for when nothing was received.
musync.MutexThe internal lock.
not_emptysync.CondVarWaking the receivers.
not_fullsync.CondVarWaking the senders.
takensync.CondVarThe signal that a value was taken, on an unbuffered channel.
chan-Chan.salam
import chan
import sync

mut jobs := chan.Chan {} as chan.Chan<i64>
mut results := chan.Chan {} as chan.Chan<i64>
mut group := sync.WaitGroup {}

func worker():
    mut open := true
    until true:
        n := jobs.recv(open)
        if not open:
            break
        end
        results.send(n * n)
    end
    sync.Done(group)
end

func main:
    jobs.init(4)
    results.init(16)
    group = sync.NewWaitGroup()
    sync.Add(group, 2)
    a := spawn(worker)
    b := spawn(worker)
    repeat 1 to 11 in n:
        jobs.send(n)
    end
    jobs.close()
    sync.Wait(group)
    join(a)
    join(b)
    results.close()
    mut total := 0 as i64
    mut open := true
    until true:
        v := results.recv(open)
        if not open:
            break
        end
        total += v
    end
    println "sum of the squares:", total
    println jobs.is_closed(), jobs.len(), jobs.capacity(), jobs.send(1)
    sync.DestroyWaitGroup(group)
    jobs.free()
    results.free()
end
Outputsum of the squares: 506 true 0 4 false

init

func init(capacity: i64)
Prepares the channel with the given capacity; zero means unbuffered.

The example for this item is shown with the ones above: chan-Chan.salam

send

func send(v: T): bool
Sends a value, waiting when there is no room. If the channel is closed it returns false.

The example for this item is shown with the ones above: chan-Chan.salam

send_timeout

func send_timeout(v: T, ms: i64): bool
Like send, but it waits at most ms milliseconds.
chan-Timeout.salam
import chan

func main:
    mut c := chan.Chan {} as chan.Chan<str>
    c.init(1)
    println c.try_send("hello"), c.try_send("again")
    println c.send_timeout("late", 20)
    mut open := true
    println c.try_recv(open), open
    _ := c.recv_timeout(open, 20)
    println "after 20 milliseconds:", open
    println c.send_deadline("a", 0, false)
    println c.recv_deadline(open, 20, true), open
    c.free()
end
Outputtrue false false hello true after 20 milliseconds: false true a true

send_deadline

func send_deadline(v: T, ms: i64, timed: bool): bool
The base of the two above: when timed is true it waits up to ms milliseconds, and otherwise forever.

The example for this item is shown with the ones above: chan-Timeout.salam

recv

func recv(ok &: bool): T
Receives a value, waiting when there is none. When the channel is closed and empty, ok turns false; the returned value then means nothing and must not be used.

The example for this item is shown with the ones above: chan-Chan.salam

recv_timeout

func recv_timeout(ok &: bool, ms: i64): T
Like recv, but it waits at most ms milliseconds. If nothing arrives, ok turns false.

The example for this item is shown with the ones above: chan-Timeout.salam

recv_deadline

func recv_deadline(ok &: bool, ms: i64, timed: bool): T
The base of the two above, with the same meaning for timed.

The example for this item is shown with the ones above: chan-Timeout.salam

try_send

func try_send(v: T): bool
Sends if there is room right now; it never waits. On an unbuffered channel it is always false.

The example for this item is shown with the ones above: chan-Timeout.salam

try_recv

func try_recv(ok &: bool): T
Receives if a value is there right now and sets ok; it never waits.

The example for this item is shown with the ones above: chan-Timeout.salam

close

func close()
Closes the channel and wakes every waiting thread.

The example for this item is shown with the ones above: chan-Chan.salam

is_closed

func is_closed(): bool
Whether the channel has been closed.

The example for this item is shown with the ones above: chan-Chan.salam

len

func len(): i64
How many values are waiting in the buffer.

The example for this item is shown with the ones above: chan-Chan.salam

capacity

func capacity(): i64
The channel's capacity.

The example for this item is shown with the ones above: chan-Chan.salam

free

func free()
Releases the channel's memory.

The example for this item is shown with the ones above: chan-Chan.salam