36 ms·
I cannot speak for Rust, but I can speak for Go. The actor model is almost the reverse of how Go handles concurrency. Instead of sending to named actors, in Gol
by GeorgeMac 12y ago
I cannot speak for Rust, but I can speak for Go. The actor model is almost the reverse of how Go handles concurrency. Instead of sending to named actors, in Golang you name your pipes (or channels). Then you handle these pipes as first class citizens and routines can choose to receive or send on them. e.g.
1. In your main routine you build a channel of ints (noticed they're typed) named `x`
2. You hand `x` and an integer i (incremented by one for each new routine) to ten routines which will double that number and send the result down `x`
3. Your main routine then receives on `x` and builds a list of results. It hasn't blocked on the doubling operations for each integer `i` because you sent each of those operations in a new routine.
Ignoring the fact I haven't managed closing the channel `x` you can get the gist of how channels are named and passed around.
I can't say what the alternative would be in Rust, but I hope that sheds more light on Go!
- steveklabnik 12y agoThis is similar to Rust: let (tx, rx): (Sender<int>, Receiver<int>) = channel(); spawn(proc() { let result = some_expensive_computation(); tx.send(result); }); some_other_expensive_computation(); let result = rx.recv(); There are some subtle details I'm not 100% sure of (bounded vs. unbounded?) that may be different, though. For more: http://doc.rust-lang.org/guide-tasks.html http://doc.rust-lang.org/guide-tasks.html
- hadoukenio 12y agoDoes anyone know how this compares to what's newly available in the standard C++11 libraries?
- GeorgeMac 12y agoRight so you name the sender and receiver right? Then say a channel exists between them? Then send and receive are explicitly called on the sender and receiver respectively. Which is the opposite of how Go names the channel and the `sender` is the routine which calls a send `x<-` on the named channel. The `receiver` in Go would be the main routine which calls receive on the named channel `<-x`. I think that is the subtle difference.
- dragonwriter 12y ago> Right so you name the sender and receiver right? No, you create a channel with a sender and receiver handle, and then the tasks that are going to send or receive use those handles. You can think of send and receive handles as loosely analogous to send- or receive-only channels in Go (they are slighty different because only one task can use each handle, but they are cloneable to allow multiple tasks to use the channel, it just forces multiplexing on either end to be more of an explicit choice.)
- rakoo 12y agoThis is completely the opposite: in Rust you have an explicit sender and an explicit receiver, and you have no control on the channel that was created. Only this sender can send to the pipe, and only this receiver can receive. In go, all you have is the channel. Anyone can send to it/read from it: c := make(chan int) go func() { // I can write here c <- 1 }() go func() { // I can also write here c <- 2 }() // I can read here, even though I have no idea who wrote to the channel for a := <- c { // Note that since I don't know who wrote to c, I can't expect // any order here. All I can do is process stuff that is coming // down the pipe (which is all I really care about after all }
- dragonwriter 12y ago> This is completely the opposite: in Rust you have an explicit sender and an explicit receiver, and you have no control on the channel that was created. Only this sender can send to the pipe, and only this receiver can receive. Its not "completely the opposite", though it is different. Rust doesn't let multiple tasks use the same sender handle, but supports multiple senders on the same channel by cloning the sender handle (same with the receiver handle, mutatis mutandis.) So your Go code becomes something like this in Rust (the only substantive difference is the need to clone the sender handle): let (tx, rx) = channel(); spawn(proc() { tx.send(1); }); tx2 = tx.clone(); spawn(proc() { tx2.send(2); }); for a in rx.iter() { // As in the Go example, process the stuff coming down // the channel with no expected order or knowledge of // who sent to it. }