7 comments

[ 2.9 ms ] story [ 19.1 ms ] thread
here's a preprint of the 3 layer cake article referenced in blog post (Johnson is, of course, the Gang of 1:

http://www.upcrc.illinois.edu/workshops/paraplop10/papers/pa...

and also this deck on Go/clojure/scala/erlang for comparison

http://kachayev.github.io/talks/kharkivpy%230/#/26

__________

Haven't coded in erlang in a long time, but the phrase "unbounded lifetime of actors" seems to be the antithesis of how actors are used in erlang and akka... need to read more about rust

Never used akka; but in erlang, actors (processes) are frequently long-lived, which is what he means by "unbounded lifetime. An erlang process generally doesn't do a single computation and then join back with the spawning process; instead, it usually stays alive as long as the resource it is managing is alive.

For example, in a chat server, you might have one process per user, and one process per channel; when someone says something, it's passed via TCP to the user process, which passes it to the channel process, which hands it out to the other user processes, which send it back to their users. Each of the user processes and channel process are long lived; they are there to sit around idle until they need to react to an event, at which point they wake up, do their work, and go back to sleep until another event comes along.

Fork-join, instead, is about shorter-lived processes, that are treated essentially as parallel subroutines, and go away as soon as that computation is done.

Note that both actors and fork-join may be mapped to long-lived hardware threads, but both are used fairly differently; I see a pretty big distinction between long-lived Erlang actors and short lived fork-join patterns. And of course, you can emulate fork-join with actors, but based on the paper you linked to, it sounds like there might be some efficiency benefits from treating them differently.

Could that just be mitigated by spawning a pool of processes (there are multiple examples, one even in the LYSE book) and then executing the computation then returning them to the pool?

This basically follows the "Erlang process is quickly checked out of the pool, runs a single computation and returns back to the pool"

Can someone explain to me why it's not possible to have two mutable borrows of a pointer with overlapping lifetimes? Under what circumstances would this be unsafe in single-threaded code?
Iterator invalidation. If we didn't have that rule you could write this:

    let mut vector = ~[ 1, 2, 3, 4, 5 ];
    for vector.each_mut |x| {
    //                   ^ mutable reference
        for 5.times {
            vector.pop();
    //      ~~~~~^ mutable reference
        }
        println((*x).to_str()); // segfault: invalidated iterator
    }
I posted this as a separate submission but Nico posted the followup post [1] mentioned at the end of the opening paragraph:

> In particular, the existing borrow checker rules, which were aimed at preventing dangling pointers, turn out to be extremely well-suited to this task. I find this very interesting and very heartening as well, and I think it points to a kind of deeper analogy between memory errors in sequential programs and data races in parallel programs. I will elaborate on this theory in a later post.

[1] http://smallcultfollowing.com/babysteps/blog/2013/06/11/on-t...