tasks
Tasks (go) and channels. Natively each task is a thread, and they run at
the same time; the output is still the same on every run, because main
prints only what it receives, in the order the channels give it. Tasks share
nothing but channels. (In a #![hosted] program they take turns on the VM.)
jihoo run examples/tasks.jhenum Msg { Item(i64) Done}
// Sends `from..to`, then `Done`.fn numbers(out: chan Msg, from: i64, to: i64) { let i = from while i < to { send(out, Msg.Item(i)) i = i + 1 } send(out, Msg.Done)}
// Applies `f` to every item until `Done`, which it passes on.fn stage(input: chan Msg, out: chan Msg, f: fn(i64) -> i64) { let running = true while running { match recv(input) { Item(x) => send(out, Msg.Item(f(x))) Done => { send(out, Msg.Done) running = false } } }}
fn is_prime(n: i64) -> bool { if n < 2 { return false } let d = 2 while d * d <= n { if n % d == 0 { return false } d = d + 1 } return true}
fn main() { // A pipeline: numbers -> square -> add one -> main. let a = chan(Msg) let b = chan(Msg) let c = chan(Msg, 8) // buffered: the last stage can run ahead go numbers(a, 1, 6) go stage(a, b, fn(x) { return x * x }) go stage(b, c, fn(x) { return x + 1 }) let running = true while running { match recv(c) { Item(x) => print(x) // 2 5 10 17 26 Done => running = false } }
// A worker pool: each worker counts the primes in its own range. let results = chan(i64) let workers = 4 let w = 0 while w < workers { let lo = w * 2500 go fn() { let count = 0 let n = lo while n < lo + 2500 { if is_prime(n) { count = count + 1 } n = n + 1 } send(results, count) }() w = w + 1 } let total = 0 let k = 0 while k < workers { total = total + recv(results) k = k + 1 } print("primes below 10000: " + to_str(total)) // 1229}