PistonDevelopers / dyon

A rusty dynamically typed scripting language

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

For-in loop for concurrency

bvssvni opened this issue · comments

Dyon uses "in-types" to communicate across threads. A common pattern when receiving data is the following:

fn report(a: in[[f64]]) {
    loop {
        x := next(a)
        if x == none() {break}
        x := unwrap(x)
        print(x[0])
    }
    println("")
}

With the for-in loop, one can write:

fn report(a: in[[f64]]) {
    for x in a {print(x[0]}
    println("")
}

The syntax is similar to the iterator pattern in Rust. Dyon does not have iterators at this moment, but the semantics is very similar. The loop is sequentially executed like in Rust, but the data generated might come from several threads at once.

In the future, Dyon might get iterator/generator syntax, which probably will use the same in-type.

The for-in loop breaks when there are no new messages. A common pattern is to create an extra in-type to signal when a task is complete and use a counter to detect when all tasks are complete:

fn log(a: f64) {}

fn finish() {}

fn bar(id: f64, n: f64) -> bool {
    for i n {
        log((id + 1) * 1000 + i)
        sleep(0.1)
    }
    finish()
    return true
}

fn main() {
    log := in log
    finish := in finish
    n := 10
    for i n {_ := go bar(i, 2)}
    loop {
        for msg in log {println(msg[0])}
        if n == 0 {break}
        for done in finish {n -= 1}
    }
}

Notice that the check if n == 0 {break} happens after emptying the queue for messages, but before decrementing the counter. This makes sure that there is no data race.

Design:

  1. Use Rust's syntax for iterators to read messages from in-types in Dyon
  2. Extensible for other kinds of patterns in the future such as iterators/generators

Rules:

  1. Non-blocking (similar to next).
  2. Must be wrapped in a loop with proper checks to avoid data races.