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) }
}