Live data from Hacker News

Notes on structured concurrency, or: Go statement considered harmful

vorpus.org

11–20 of 234 posts

Re: Notes on structured concurrency, or: Go statement considered harmful

#14
post #11

How is this different than calling join(), after spawn()?

How is if different that just using goto to go to either the true or false clause? It isn't about what you can do, it's about what you can't do if you use this mechanism (this restricts where you can call spawn and join) and the guarantees you can then build on top of that.

Re: Notes on structured concurrency, or: Go statement considered harmful

#15

This is very very long to explain a very simple pair of ideas: 1) You should be able to declare scoped blocks that mandate execution of all tasks started in that block ends when the scope ends. 2) This is fundamentally superior to all other forms of concurrency. I get it; this is basically what async/await gets you, but conceptually you can spawn parallel tasks inside an awaited block, and know, absolutely that all o…

Or Promise.all/Promise.reject for that matter.

Re: Notes on structured concurrency, or: Go statement considered harmful

#16
I’m wondering if some promise/future systems already provide a similar guarantee. The main useful property of the nursery system is that a function’s signature indicates whether that function leaves a background task running. If you can guarantee that promises/futures are dropped if they go out of scope, then you get a similar guarantee. Similarly, if you have a system where promises don’t actual run their background parts unless someone is waiting for them, then there are no leaky background tasks.

Re: Notes on structured concurrency, or: Go statement considered harmful

#17
post #4

There are other approaches. State machines, reactors are often used in low level layers and the Actor model for some high level design.

When you add in queues for passing things back and forth between the async functions, I think this boils down to an Actor model. The nursery would be equivalent to supervisors in Erlang.

Re: Notes on structured concurrency, or: Go statement considered harmful

#18
post #3
post #2

I thought the title was kinda clickbaity, but it turned out to be a great article. Also the comparison to goto really effectively conveyed the point he was trying to make. I have two questions though: * Does anything else like this currently exist (other than the Trio library he mentions), which shows that it's a superior paradigm in practice? * What are the cons to this approach? Why not do it?

I don't think its a superior paradigm, just a different one. I only see his nursery as being useful when you really want your async tasks to complete before the function in which they were dispatched returns. That's far from covering every use case of concurrency! A lot of the value of concurrency is in background operations. These simply can't be tied to the duration of a function call on the dispatch thread. Doing…

> I only see his nursery as being useful when you really want your async tasks to complete before the function in which they were dispatched returns. That's far from covering every use case of concurrency!

His section "There is an escape" answers this criticism: "The nursery object also gives us an escape hatch. What if you really do need to write a function that spawns a background task, where the background task outlives the function itself? Easy: pass the function a nursery object."

He goes on to explain a bit more, but one of his points is what really ties this abstraction back into the goto discussion: "Since nursery objects have to be passed around explicitly, you can immediately identify which functions violate normal flow control by looking at their call sites, so local reasoning is still possible."

> A lot of the value of concurrency is in background operations. These simply can't be tied to the duration of a function call on the dispatch thread.

I think they can: applications with background threads would have an outer-level nursery at whatever "main" is for them, and that nursery would be passed into whatever function needs to spawn a background thread.

Re: Notes on structured concurrency, or: Go statement considered harmful

#19
What.

This article proposes a "nursery", which is just a wrapped sync.WaitGroup/pthread_join/futures::future::join_all/a reactor that waits for all tasks to terminate/etc.

It then uses an exception-like model for error propagation to "solve" error handling (which is fairly easy to handle with a channel).

The construct is a decently usable, already applied tool to handle a set of problems, but the article takes the issue way out of proportions and overhypes the proprosed solution. The "with" example for benefits to not having a "go" statement seem rather bogus, especially seeing that such RAII constructs do not exist in Go (no destructors, remember?).

Trying to claim that "go" is as terrible as the original "goto" is ignorance of the original problems. Bad use of goto can be a nightmare to track (as the author tried to illustrate), but goroutines do not jump around, they branch from the main goroutine, following normal control flow from there. They are easy to follow, and the language is designed so that you can throw around with them and forget them without them causing you problems.

Also, this article is comparing a list of concurrency constructs and one parallism construct (pthread_create—threading.Thread doesn't count as parallism due to GIL) to callbacks, something which have nothing to do with concurrency at all. Very odd.

Re: Notes on structured concurrency, or: Go statement considered harmful

#20

Didn't expect to say this, but the article is completely right! This is obviously the right way to write concurrent programs. Kudos for writing this. One question though. The first part of the article says that "onclick" handlers should be replaced with nurseries as well. But I don't see how. Can someone explain?

I suspect that if you were to try to do this in real code, something like an onclick handler would have to be run in a nursery scoped at the page level, by the code running the page. An onclick handler on its own accord can't run itself in the correct nursery. It's like the network handling case there, where the nursery's lifetime is either unbounded, or tied to the lifetime of the OS process, depending on how you want to look at it. Functions don't always return within a program, or at least, don't always return excepting maybe a last cleanup as the program terminates.
Post reply on HN