Hi,
I've recently watched a Google I/O talk on Go Concurrency Patterns [1]
and I find some patterns worrisome. Go has made some choices, but I'd
like to understand how Rust addresses these issues.
Disclaimer on my background: I've learned programming mostly in C, then
a bit of Lisp, a good share of Java, then for the last few years an
intense dive into JavaScript (including node.js for almost a year).
It's very likely that this cultural background influences (a lot!) my
view on programming languages (something about a hammer and a nail).
Most of my concerns are appearant in the following piece of Go code
(32'41'' in the video):
c:= make(chan Result)
go func() { c <- Web(query) } ()
go func() { c <- Image(query) } ()
go func() { c <- Video(query) } ()
timeout := time.After(80*time.Milliseconds)
for i:=0; i<3; i++ {
select{
case result := <-c
results = append(results, result)
case <- timeout
fmt.Println("timed out");
return
}
}
return
The intention here is to do a search in different servers (Web, Image,
Video) and produce a result ('append' function) with these results.
3 goroutines (background tasks) and the "main" goroutine synchronously
blocks on either the c channel (on which each coroutine may write
eventually) or the timeout.
My analysis goes as follow:
Due to synchronous wait, the 3 server queries have to be done in 3
goroutines, otherwise, they would block the "main" goroutine or one
another. Each goroutine costs something (both for memory creation and
certainly scheduling too).
Then, because of synchronous blocking, again, you need a select block to
enable multiplexed listening of blocking waits.
Finally, maybe it was only for the purpose of an example, but the 'i'
variable is an abstraction of exactly nothing. What we really care about
is either that the result is fully composed (after all partial results
came back) or we timedout and this code doesn't make this expectation
straightforward to read.
Somewhere in the video is mentionned that synchronous blocking is a
feature meant for concurrent tasks synchronization. My experience with
JavaScript is synchronisation is the exception rather than the normal
case, but that might be the biais I talked about above (and I use
promises for synchronisation for their expressivness).
So I have several questions regarding Rust:
* Is synchronous blocking possible?
* How does Rust deal with concurrent tasks synchronization?
* How would you write the above example in Rust?
* Do you think it's satisfying in terms of expressiveness?
Rust is being used in the Servo project, itself aiming at building a web
browser. We've seen in the Snappy effort (and some other before that)
that encouraging asynchronisity is key in building responsive and
efficient software, hence all my questions about Rust take on synchronisity.
David
[1] http://www.youtube.com/watch?v=f6kdp27TYZs