7 ms·
Structured Concurrency
- _ZeD_ 5y agoObligatory trio link https://trio.readthedocs.io/en/stable/ https://trio.readthedocs.io/en/stable/
- mns06 5y agoAlso worth being aware of AnyIO which implements structured concurrency on top of asyncio, and serves as an abstraction layer over trio/asyncio. https://anyio.readthedocs.io/en/stable/ https://anyio.readthedocs.io/en/stable/
- pizza 5y agoThere's a proposal for a really nice form of structured concurrency in c++ https://ericniebler.com/2021/08/29/asynchronous-stacks-and-scopes/ https://ericniebler.com/2021/08/29/asynchronous-stacks-and-s...
- parksy 5y agoIs the basic concept of structured concurrency more about programming language design, or applicable to how a program is structured? I can do something like this in JS: async function doTasks(tasks = []) // Do some concurrent stuff: let results = await Promises.all(tasks.map((task) => new Promise((resolve, reject) => { workerpool.exec('mytask', [task]) .then(function(result) { resolve(result) }) .catch(function(err) { reject(err) }) }))) // Function pauses here until all tasks resolve. // do stuff with results } The workerpool exists outside the scope of this function, is that kind of the crux of the distinction, or does it come down to how threads / workers are managed (by the language / first class constructs) that outlines the definition of structured concurrency? The example above feels like a similar pattern to what I've seen in discussions of structured concurrency but as with most things I feel like there's an aha moment where I'll get what all the fuss is about.
- Matthias247 5y agoIn my opinion it's mostly a pattern where you make sure that all sub-tasks are fully contained within child tasks and never outlive them. You can model that patten in most programming languages - e.g. as you do in JS. However there can be environments which have structured concurrency baked in and thereby enforce the pattern. Kotlin coroutines are one example here.
- parksy 5y agoSo I guess my example resembles some form of structured concurrency but the threads are not encapsulated in the parent's closure. I still need to structure my promises and await / async logic to deal with the edge cases and make sure the program doesn't get stuck or leave threads hanging. That makes sense, thanks.
- cowboyd 5y agoI think the simplest expression of the idea of structured concurrency that I've come across is this: The scope of any concurrent process is the same as the lexical scope of the function that created it. This has profound implications. Let's say, for example that I call `doTasks()` with 10 separate tasks. Before any of them can complete, one of them fails. What happens to the other 9? In your example, they are "leaked" because they will continue running, even though the scope that was awaiting their results in gone. Using a "worker pool" as in the example, it might go something like this: async function doTasks(tasks = []) { let workerpool = new WorkerPool(); try { for (let task of tasks) { workerpool.exec("my task", task); } let results = await workerpool.all(); // do stuff with results } finally { // no matter the outcome, nothing outlives this scope. await workerpool.destroy(); } } It should be noted that cancellation, i.e. the ability to "destroy" a concurrent task is a necessary primitive for structured concurrency. You can think of it as the equivalent of automatically releasing memory at the end of a lexical scope. There is already an implementation of Structured Concurrency for JavasScript here https://frontside.com/effection https://frontside.com/effection
- parksy 5y ago
- cowboyd 5y agoFor those interested in exploring Structured Concurrency in JavaScript, there is https://frontside.com/effection https://frontside.com/effection
- ghoward 5y agoJust so you know, those of us who believe in structured concurrency often have slightly different meanings (which I believe will converge over time). My definition is at [0]. Beyond libdill, a rough version has now been implemented in C. (By me, sorry for shilling.) An example of it in code is at [1]. Combine it with something I call a stackpool (basically a heap-allocated replacement for `alloca()`), and you can worry very little about managing memory manually, even in C. In fact, both together can even serve the same purpose as Rust's borrow checker in C, if you are willing to write your code with a certain style. Once I implement it as a first-class construct in a language (which I'm doing right now), it will look like this: threadset { // This starts a thread. go run_thread(arg1, arg2, etc); // The current thread does not leave // this block until all threads finish. } I'm happy to answer questions. [0]: https://gavinhoward.com/2019/12/structured-concurrency-definition/ https://gavinhoward.com/2019/12/structured-concurrency-defin... [1]: https://git.yzena.com/Yzena/Yc/src/commit/30f4ae4e471cb5a500da85812619199b4bda5450/src/rig/build.c#L962-L1010 https://git.yzena.com/Yzena/Yc/src/commit/30f4ae4e471cb5a500...
- frankpf 5y agoWould you say that Java's Loom[1] matches your definition of structured concurrency? [1]: https://www.javaadvent.com/2020/12/project-loom-and-structured-concurrency.html https://www.javaadvent.com/2020/12/project-loom-and-structur...
- gavinhoward 5y agoAfter reading that post, I'm pretty sure that Project Loom only fits my definition of structured concurrency if it's used solely with the try-with-resources construct. However, if it is used that easy, then yes, absolutely, it fits my definition. Using the Executor class as a threadset might also make it fit my definition, but I think my opinion of my definition has changed in the two years since I wrote it. I may have to revisit it because I think it may be useful to only consider concurrency that has the same block structure as structured programming does, whereas my current definition allows for passing a threadset around as a first-class value. tl;dr: yes, it probably fits, but that might mean my definition need changing, except in the case of try-with-resources.
- speps 5y ago(2016)
- chrisbrandow 5y agoGlad you noted this. I was reading it thinking odd that it made no mention of Swift and it’s recent implementation.
- muxator 5y agoI just wanted to mention that this is taken from the blog of Martin Sústrik, one of the original authors of ZeroMQ.
- ibraheemdev 5y agoAnd possible related to the recent post of one of his projects, libmill: https://news.ycombinator.com/item?id=30699829 https://news.ycombinator.com/item?id=30699829, where libdill [0], "Structured Concurrency for C" was also mentioned. [0]: http://libdill.org/ http://libdill.org/