Concurrency: spawn, Threads and Channels
24.1 spawn (OS Threads)
spawn runs a function on a new OS thread. go was historically planned for lightweight coroutines (green threads, an experimental runtime). Today go and spawn behave similarly; check the current docs.
thread without a return type: mut ths := []thread{} then ths.wait().
import time
fn compute(id int) int {
time.sleep(100 * time.millisecond)
return id * id
}
fn main() {
t := spawn compute(5) // returns thread int
result := t.wait() // block and get the return value
println(result)
mut threads := []thread int{}
for i in 1 .. 6 {
threads << spawn compute(i)
}
results := threads.wait() // wait for all; returns []int
println(results)
}24.2 Channels
fn producer(ch chan int) {
for i in 0 .. 5 {
ch <- i // send
}
ch.close()
}
fn main() {
ch := chan int{cap: 10} // buffered channel (cap: 0 = unbuffered)
spawn producer(ch)
for {
v := <-ch or { break } // receive; `or` handles a closed channel
println(v)
}
println(ch.len)
println(ch.cap)
println(ch.closed)
ok := ch.try_push(1) // non-blocking
_ = ok
}24.3 select
import time
fn main() {
ch1 := chan string{}
ch2 := chan int{}
spawn fn [ch1] () { ch1 <- 'hello' }()
spawn fn [ch2] () { ch2 <- 42 }()
for _ in 0 .. 2 {
select {
s := <-ch1 { println('string: ${s}') }
n := <-ch2 { println('int: ${n}') }
500 * time.millisecond { println('timeout') } // timeout branch
}
}
}24.4 Worker Pool Pattern
sync.pool provides a parallel processing pool (pool.new_pool_processor).
import sync
fn worker(id int, jobs chan int, results chan int, mut wg sync.WaitGroup) {
for {
j := <-jobs or { break }
results <- j * 2
}
wg.done()
}
fn main() {
jobs := chan int{cap: 100}
results := chan int{cap: 100}
mut wg := sync.new_waitgroup()
for w in 1 .. 4 {
wg.add(1)
spawn worker(w, jobs, results, mut wg)
}
for j in 1 .. 10 { jobs <- j }
jobs.close()
wg.wait()
results.close()
for { r := <-results or { break } println(r) }
}