15 ms·
Fearless Concurrency: Clojure, Rust, Pony, Erlang and Dart
- antirez 8y agoWhat's great about the actor model is that you can kinda apply it in languages not having such native support. Even if it will not be a strict model, with some education from the programmer it can do wonders and can be backed by lock free queues. What I see as a problem is always they for a thread to wait on new items a syscall must be executed which is costly. But one could use a spinlock a few cycles and later degradate to syscall.
- readittwice 8y ago> What's great about the actor model is that you can kinda apply it in languages not having such native support. Yep, although not listed in the article, JS would be such an example for me. TBH I am not entirely sure what's the difference between Web Workers and Isolates but for me it's more or less the same: Both allow safe multi-threading simply because threads do have separate heaps.
- markdog12 8y ago> TBH I am not entirely sure what's the difference between Web Workers and Isolates > dart:isolate - This library was an attempt to provide a single API that provides common concurrency functionality across Dart's web and native platforms. While useful in some cases, most users found the isolate API limiting compared to the Web Workers API. The infrastructure for supporting isolates also adds substantial overhead when compiling to JavaScript. In the future, you should use Web Workers to access concurrency on the web. > Part of the isolate API has never worked (spawnFunction) in JS platforms, and the other (spawnFile) doesn't work in Dart/AOT (Flutter). Neither are able to use transferrable/shared memory objects > On the other hand, the JS platform has evolved quite a bit since isolates were created: Web workers Service workers Animation worklets ... and other APIs like SharedArrayBuffer ... we'd like to enable our web users to seemingly use these, with as little overhead as possible From https://groups.google.com/a/dartlang.org/forum/#!topic/misc/djfFMNCWmkE https://groups.google.com/a/dartlang.org/forum/#!topic/misc/...
- mpweiher 8y agoYep, I have used Cocoa(Touch) runloops in this way. Very straightforward, particularly if you use a bit of Higher Order Messaging syntactic support: [[someObject async] doStuff]; This will schedule the doStuff message to run on the runloop of the actor (=object + runloop) in question.
- heavenlyhash 8y agoI found it interesting that the article mentions actors much at all for the same reason. It's pretty trivial to construct actors out of some other message passing system. The interesting design choices in doing so are mostly down to the semantics in A) message passing, and B) scheduling/triggering/mapping-onto-green-threads/etc. And for part A, all the other choices in the first three segments of the article are still effectively the choices that you've got to contend with: copying vs immutablity (bonus, COW mode, but still) vs ownership semantics. Or to come at it from the other way: actors are far more featureful than is appropriate to directly compare to mere message passing semantics choices, because actors generally have some concept of error handling as a result of their relationship to scheduling, and that puts them on a whole different field.
- macintux 8y agoThat’s a big reason I’m a fan of Erlang: individually, its features are interesting, but collectively they form an amazing system. Greater than the sum of its parts.
- dmix 8y agoAgreed, it's one thing to have good primitives like Go channels but Erlang/Elixir provide an entire system from which to build a concurrent/async application. Things like error handling, messaging, storage, and structuring your application well for concurrency are already basically built-in into the standard approach you take building Erlang/Elixir apps.
- lugg 8y agoWhats a tldr for how Erlang handles error handling? This is something that is usually glossed over / afterthought when it is kind of a big deal in real life programming.
- macintux 8y agoThe language is built upon a few core concepts: * Processes are extremely lightweight, orders of magnitude smaller than operating system processes or JVM threads. * Exceptions should generally not be handled; instead, those lightweight processes are allowed to fail, and an external supervisor process will re-launch if appropriate. * Assertions about the state of the data are effectively enabled on every line of code, so the processes crash early, before corrupting other parts of the system. * Data is immutable, which plays a role in making those assertions happen. You could probably strip one or two of those bullet points and/or add a couple of more, but I think that captures the highlights. I'll toot my own horn. If you find that interesting, this is my favorite talk I've given about the above: https://youtu.be/E18shi1qIHU https://youtu.be/E18shi1qIHU
- mcguire 8y agoThere are a few gotchas with actors: * they really do need M:N threading (M green threads for the actors, N system threads where N ~= #CPUs), * message queues have some complexities; it's not hard to get into a situation where messaging costs overwhelm actual work. Also, you need some form of back-pressure to keep a fast producer/slow consumer from killing everything. Pony is actually a pretty sweet design for all of these. Complicated, though.
- smallstepforman 8y agoI was really excited to discover Pony a couple of years ago, sadly there is negative momentum with this project. So much potential, yet the world isn’t ready for it yet.
- readittwice 8y agoI looked into Pony some time ago and I always found the capabilities-thing to be quite complex although very interesting. It was hard to imagine using it in a project with developers unfamiliar to this concept. Especially since I was mostly working on large web applications where only tiny parts were actually using shared state between threads. TBF I have never written Pony code, I was mostly reading documentation.
- imtringued 8y agoThe problem with fancy new programming languages is that no big company is willing to back it and then actually use it (this is the most important step). But languages without backing/usage go nowhere and then get donated to the apache or eclipse foundation.
- hackerpacker 8y agounless they invented it, then it is flying monkeys everywhere.
- espeed 8y agoYou sure about that? Sylvan Clebsch [1] -- Pony's creator -- is now part of Microsoft Research [2], has been working on a distributed actor model, and is presenting on Pony at QCon London next week [3]. [1] https://github.com/sylvanc https://github.com/sylvanc [2] https://www.microsoft.com/en-us/research/people/syclebsc/ https://www.microsoft.com/en-us/research/people/syclebsc/ [3] https://qconlondon.com/speakers/sylvan-clebsch https://qconlondon.com/speakers/sylvan-clebsch Pony: Co-Designing a Type System and a Runtime [video] https://www.microsoft.com/en-us/research/video/pony-co-designing-type-system-runtime/ https://www.microsoft.com/en-us/research/video/pony-co-desig...
- tempodox 8y ago
- ahaferburg 8y agoIn case the author sees this: The indentation of the code samples is all over the place, making it quite hard to read. Even more so for a white-space sensitive language like Pony. Did you mix tabs and spaces?
- rubiquity 8y agoPony is not white space sensitive.
- timClicks 8y agoReaders are though..
- ahaferburg 8y agoOh. Good to know, thanks. I see that there are `end` tokens, but since I don't know which tokens they correspond to, it's still hard too read.
- johnisgood 8y agoYeah, it really makes it annoying to read the code snippets. I thought Pony just looked bad in general, then I looked at the snippet of a familiar language (Erlang) and it seemed horrible, too.
- eeZah7Ux 8y ago"The problem is, that sometimes, unfortunately, these tools are just not sufficient, it's still easy to shoot your own foot and get lost in a sea of complexity." As a non-native English speaker I found this use of commas very difficult to understand. Often I get the feeling that native speakers don't even notice it.
- fyfy18 8y agoIt sounds like OP is a non-native speaker too. I'd simplify it to this: "The problem is that sometimes these tools are just not sufficient. It's still easy to shoot yourself in the foot and get lost in a sea of complexity." (Hemingwayapp is great for making sure writing is not too complex)
- seaish 8y agoThe first comma is simply incorrect. "unfortunately" does need commas around it, but it could be moved to the beginning for a simpler sentence. The fourth comma is also incorrect and should be replaced by a semicolon. "Unfortunately, the problem is that sometimes these tools are just not sufficient; it's still easy to shoot your own foot and get lost in a sea of complexity." And looking at that now, I would also get rid of "the problem is that". "Unfortunately" and "sometimes" back to back lacks flow, so I would also replace "sometimes" (in this case with "often" in place of "just"). In the original, "just not" has a stronger grouping than "not sufficient", which is why "insufficient" wasn't used. Now with "just" gone, I'd swap back in "insufficient". "Unfortunately, these tools are often insufficient; it's still easy to shoot your own foot and get lost in a sea of complexity."
- li4ick 8y agoFor those of you who want to test multiple concurrency models, I can highly recommend Seven Concurrency Models in Seven Weeks from Pragmatic.
- tirumaraiselvan 8y agoSorry, I do not know any of these languages but I have used Haskell's STM which is incredible. Any of the languages mentioned here close to the STM idea (basically using strong types to ensure mutations happen in isolated context)?
- rubiquity 8y agoPony’s does this with the added benefit that all the checks happen at compile time. I’m only somewhat familiar with STM and think some of the safety checks are at runtime but could be wrong.
- Tehnix 8y agoThe safety checks are at compile-time, since it only allows pure functions to be run. You can circumvent this of course with unsafePerformIO, but then you are completely on your own.
- Shoue 8y agoOne of the issues with STM is you can't use IO inside the atomic blocks, which is easy enough to get around but if your users are unaware it'll present bugs. Haskell enforces a separation of IO at the type-level, hence this risk is gone so you get every benefit of STM with none of the risk. STM itself eliminates a set of concurrency problems based on the way it works, but you do still have to do some run-time checks to eliminate deadlocks (i.e. use `modify` functions or have the atomic blocks behave like them, or you could end up with a deadlock).
- nickik 8y agoThe idea of STM has nothing todo with strong types. You can have STM with types or without. Clojure has a full STM since version before version 1.0. Simple example: (def stm (refs {})) (alter! stm assoc :testkey "testvalue") (println @stm) See: https://clojure.org/reference/refs https://clojure.org/reference/refs
- tirumaraiselvan 8y ago
- rainygold 8y agoYou can also use Actors and elements of the OTP from Erlang in Clojure via certain libraries.
- duneroadrunner 8y agoI'll just mention that if you're using C++, the SaferCPlusPlus library[1] supports a data race safe subset of C++, vaguely analogous to Rust's. [1] shameless plug: https://github.com/duneroadrunner/SaferCPlusPlus#multithreading https://github.com/duneroadrunner/SaferCPlusPlus#multithread...
- mhd 8y agoSpeaking of concurrency, is there a current environment that does something similar to Linda? I always thought that sounded quite promising, but apparently that generally is a death sentence (I also liked Modula-3, the Palm Pre and Tcl).
- timClicks 8y agoI think that creating a Linda engine is a chicken/egg problem. If there are no applications that are using the paradigm, then there's no need for a highly performing engine.
- falcolas 8y agoI have a, perhaps unjustified, concern at the loss of fear around things like concurrency. People keep substituting appeasing the compiler with actual thinking around hard problems. But until the halting problem is solved at a compiler level (at a level that can account for runtime cases), you should always have a healthy amount of fear when writing concurrent code. Fear, and respect, the absurdly difficult challenge that is writing correct concurrent code, even when your compiler is helping you out.
- cttet 8y agoYes there will still be fear sometimes, but the point of the compiler is to help people to be fearless sometimes. The halting problem does not need to be solved, since no program in practice runs forever. In some of the environments like C we don't have a way to specify finite things, where cases would be enumerable and safety guaranteed. To be fearless sometimes greatly reduces the mental workload of programmers and people who read other people's code.
- seanmcdirmid 8y agoIt is impossible to ever handle concurrency completely at the compiler level. We can handle them at the runtime level (via things like transactional semantics and timewarps), though the overhead can be great.
- deleted 8y ago[deleted]
- zzzcpan 8y agoI'm not sure I understand the argument, why is the halting problem even important here? Surely a compiler can split loops into ones that halt so they only run a little bit at a time. But you don't necessarily need a compiler for that, OS can help too and, for example, invoke a signal handler from which you can stop currently running actor. Actors can be safely stopped, destroyed, preempted, etc. without breaking other actors.
- ekidd 8y ago> Fear, and respect, the absurdly difficult challenge that is writing correct concurrent code, even when your compiler is helping you out. There are plenty of safe and easy models for writing concurrent code. Here's a famous one that's easy to overlook: gzip -cd compressed.gz | grep error On Unix, this doesn't use a temporary file. It creates two concurrent processes. The first decompresses a file and writes it to a pipe, and the second reads from a pipe and searches for a string of text. You could call this "coroutines over a stream," I suppose. And of course, people have been writing shell pipes for decades without concurrency errors. Unix enforces process isolation, and makes sure all the data flows in one direction. Now, there's no reason a programming language couldn't enforce similar restrictions. For example, I've spent the last few years at work writing highly concurrent Rust code, and I've never had a single case of a deadlock or memory corruption. One slightly trickier problem in highly concurrent systems is error reporting. In the Unix example, either "gzip" or "grep" could fail. In the shell example, you could detect this by setting "set -o pipefail". In Erlang, you can use supervision trees. In Rust, sometimes you can use "crossbeam::scope" to automatically fail if any child thread fails. In other Rust code, or in Go, you might resort to reporting errors using a channel. And I've definitely seen channel-based code go subtly wrong—but not necessarily more wrong than single-threaded error-recovery code in C. With the right abstractions, writing concurrent code doesn't require superhuman vigilance and perfection.
- nickpsecurity 8y agoAnd Eiffel Scoop which is always forgotten: https://en.wikipedia.org/wiki/SCOOP_(software) https://en.wikipedia.org/wiki/SCOOP_(software) https://www.eiffel.org/doc-file/solutions/eth-46802-01.pdf https://www.eiffel.org/doc-file/solutions/eth-46802-01.pdf It was ported to Java in a student project. That means other languages without great concurrency could probably use it with macros or a preprocessor.
- fogetti 8y agoI am not sure but I think Go channels were inspired by CSP (communicating sequential processes) which is not inherently unsafe though.
- leshow 8y agofrom the article: > Notice that this article does not include Go, a language that admittedly has an elegant concurrency solution as well (Go channels) because that solution is not actually thread-safe - it's not very hard to have race conditions in Go or corrupt state because Go does not enforce a separation of shareable and not-shareable mutable state.
- hn98823993 8y agoThat's incorrect though. It's impossible to have data races with Go channels. The example the author gives doesn't use them.
- jerf 8y agoMy vote for Go's #1 mistake isn't the popular "lacking generics", but missing the opportunity to have fearless concurrency, and making it so that goroutines can only communicate via immutable shared values and copied values. If you want to optionally and explicitly penetrate that barrier sometimes, I'd be OK with that, but this should be the default. Generics will probably be added after the fact 10 years after the 1.0 release. They may not be quite as slick as something that was in there from the beginning, but based on the many other languages that added them after the fact, it'll probably work out well enough. Fearless concurrency can't be added to a language; if it's not in there from the beginning it'll never be added. It's a change so big it's almost automatically a new language. And, as can be logically deduced from that statement, I am aware that it would have some additional effects in the language, such as introducing immutability, it wouldn't be simply what we now know as "Go" with just a minor tweak. I'm comfortable with that. Even with Go's focus on simplicity, I do think there was a slight error towards being a bit simpler than the problem permits here. (I do pretty well with Go's concurrency, but I was first trained brutally by Erlang and Haskell. I see those who don't come by the same route have more trouble.)
- platz 8y ago> it seems quite a lot easier to manage concurrency in Clojure from my biased point-of-view. Assuming you know that none of the code in your concurrent blocks are is side-effecting, which may be hard to know if it's not your code; Haskell checks this for you, so to me it seems easier in haskell, not harder, because I don't have to hunt down and read all the source code to know if what I'm doing has concurrency bugs or not.
- johnisgood 8y agoI am surprised it does not mention Ada. I really feel like that Ada is not getting enough attention, it definitely deserves more. Even if you have heard of the language before, please do check out some of the resources available, you will not regret it! It has been supporting multiprocessor, multi-core, and multithreaded architectures for as long as it has been around. It has language constructs to make it really easy to develop, say, embedded parallel and real-time programs. It is such a breeze. I admit I am not quite sure what they are referring to by fearless, but if it means that they can handle concurrent programming safely and efficiently in a language, well, then Ada definitely has it. Ada is successful in the domain of mission-critical software, which involves air traffic control systems, avionics, medical devices, railways, rockets, satellites, and so on. Ada is one of the few programming languages to provide high-level operations to control and manipulate the registers and interrupts of input and output devices. Ada has concurrency types, and its type system integrates concurrency (threading, parallelism) neatly. Protected types for data-based synchronization, and task types for concurrency. They of course can be unified through the use of interface inheritance, and so on. If you are interested in building such programs, I recommend two books: https://www.amazon.com/Building-Parallel-Embedded-Real-Time-Applications/dp/0521197163 https://www.amazon.com/Building-Parallel-Embedded-Real-Time-... https://www.amazon.com/Concurrent-Real-Time-Programming-Alan-Burns/dp/0521866979 https://www.amazon.com/Concurrent-Real-Time-Programming-Alan... ...other good resources: https://en.wikibooks.org/wiki/Ada_Style_Guide/Concurrency https://en.wikibooks.org/wiki/Ada_Style_Guide/Concurrency https://www.adacore.com/uploads/books/pdf/AdaCore-Tech-Cyber-Security-web.pdf https://www.adacore.com/uploads/books/pdf/AdaCore-Tech-Cyber... The last PDF will summarize in what ways Ada is awesome for: - contract-based programming (with static analysis tools (formal verification, etc.)) - object-oriented programming - concurrent programming - systems programming - real-time programming - developing high-integrity systems and a lot more. It also gives you a proper introduction to the language's features.
- weberc2 8y agoWe learned some Ada in school. I really liked it, but the free toolchain was poor (hard to get working properly, unintuitive) and the community stubbornly defended its various idiosyncrasies like its verbose Pascal syntax and its homegrown project file format. Most importantly, it just didn’t heave much of an open source ecosystem, and the community was pretty hostile and defensive toward newbies. But yeah, the language was neat! :)
- tombert 8y agoI'm a bit surprised that there didn't appear to be any mention of Clojure's built-in concurrency support outside of basic immutability. core.async gives a nice channel-based system, agents give an actor-ish system, and STM/atoms let you mutate the variable safely, without having to manually work with locks. This is definitely a good high-level article, just something I was surprised by, since core.async is what drove me (and several other people I know) to start using Clojure. EDIT: Just a note that I know core.async isn't built in, that was a mistake. It is a first-party library, however.
- burittoTTY 8y agoIndeed, Clojure also has unfettered access to Java's concurrency primitives.
- throwaway2-32 8y ago52 major open issues, 2 critical issues, and 38 others major issues list memory leaks. https://dev.clojure.org/jira/secure/IssueNavigator.jspa?reset=true&jqlQuery=project+%3D+ASYNC+AND+resolution+%3D+Unresolved+AND+priority+%3D+Major+ORDER+BY+key+DESC&mode=hide https://dev.clojure.org/jira/secure/IssueNavigator.jspa?rese... first-party?
- bgorman 8y agoCore async is maintained by Cognitect (maintainers of Clojure). It is very commonly used, and it has been upgraded to mesh well with the rest of the language over time (namely support for transducers).
- tombert 8y agoI don't really know what that has to do with anything; every piece of software has bugs. I haven't really encountered any issues with core.async yet. I suspect you could find similar bugs in nearly any popular concurrency library. By first-party, I mean it seems to be officially part of the Clojure ecosystem, the docs are hosted on the main site: https://clojure.github.io/core.async/ https://clojure.github.io/core.async/
- 8y ago
- Lorkki 8y agoThe Rust examples seemed a little bit oddly structured to me; the case of collecting a value from a single thread would be just as easily solved by returning from the closure and receiving it through join(): https://gist.github.com/lorkki/e7386df8fff186b3e473994e9d31bee0#file-thread-example-1-rs https://gist.github.com/lorkki/e7386df8fff186b3e473994e9d31b... The power of channels could be illustrated better by adapting the next example to show how you can avoid shared state completely: https://gist.github.com/lorkki/e7386df8fff186b3e473994e9d31bee0#file-thread-example-2-rs https://gist.github.com/lorkki/e7386df8fff186b3e473994e9d31b... It's also worth noting that a more versatile channel implementation than mpsc can be found in the crossbeam crate, in case you're thinking of using them for anything more serious.
- pizlonator 8y agoWhether or not this is "fearless" depends on your point of view. As a long-time pthreads programmer, these systems feel like skittish concurrency. It's for folks who are too afraid to use the underlying concurrency primitives, like shared memory, synchronization of some kind provided by OS, threads.
- felixgallo 8y agoExactly. Because the recorded history shows those constructs are nearly impossible to use correctly.
- Animats 8y agoYes. Having spent too much time debugging code by people who thought they were clever enough not to need language safety, I want language-level protection. (Did the Python crowd ever fix the race condition in CPickle?[1] They were in denial about this about eight years ago when I reported it. Doing multiple CPickle operations in separate threads can crash CPython. If you search for "CPickle thread crash" you find many reports of hard to reproduce problems in that area.) [1] https://bugs.python.org/issue23655 https://bugs.python.org/issue23655
- int_19h 8y agoI don't see a denial in that bug report - they're just saying that they don't have an actionable repro, and don't know how to get one.
- pizlonator 8y agoFalse. Lots of software uses pthreads and its direct wrappers. Correctly? What does anyone ever do correctly in software? Does anyone write GUIs correctly? Does anyone do databases correctly? Proving even simple software correct is an enormous endeavor that most pragmatic programmers simply never have the luxury to do. So proclaiming that threads are bad because nobody does them “correctly” is setting an arbitrarily high standard. Or maybe you just don’t know what that word means.
- crimsonalucard 8y agotechnically node achieves it as well.
- lelf 8y ago> Its use of dynamic typing makes me a little bit hesitant to use it, though, as I really love the help provided by static typing. There is dialyzer, a static type (and not only) analysis tool for Erlang. It is part of Erlang/OTP (i. e. built-in.) http://erlang.org/doc/apps/dialyzer/users_guide.html http://erlang.org/doc/apps/dialyzer/users_guide.html
- NickM 8y agoYeah as a long-time Erlang dev I would strongly recommend Dialyzer to anyone trying to build a serious Erlang project. It doesn't give you quite the same level of rigor that a strong typing system would, but it is nice to be able to spec out types on an as-needed basis while letting it infer types in other parts of the code. It kind of ends up feeling like a nice middle ground between static and dynamic typing, in my experience.
- punnerud 8y agoWhat about picking jobs from an SQL-table as writing back with a check? I naver had any of the problems specified on a multi-core/process system.. or have I just been lucky or blessed by ignorance?
- pornel 8y agoThat's an example of shared-nothing message-passing system, which is a perfectly valid solution. It's implementable in all the aforementioned languages.
- aimatt 8y agoMan the indentation in this article is confusing me.
- kccqzy 8y agoI'd also like to mention cooperative concurrency. I know the author kind of skipped over this from the first sentence of the article where he defined a concurrent program as having more than one thread of execution. But with coroutines, we can have a single threaded-application that handles multiple tasks concurrently too. In fact I believe this is much easier to reason about for the programmer: the kernel won't randomly decide this thread's time slice is up in the middle of an important data operation; the programmer knows exactly when an operation may cause the current task to be "descheduled" because those are usually explicitly tagged with the "await" keyword. In my experience, this model eliminates the vast majority (but not all) of the use cases for locks and other synchronization primitives. It is also very performant. Take a look at Python's asyncio, which has been in the standard library for years, and you'll see how easy it is to write concurrent networking code without threads and with very very few uses of locks.
- lugg 8y agoDid you just say single threaded concurrently reasoned applications are more performant than multithreaded applications? Trying to reason about how this could be possible. I'm still amazed by the performance you can get out of async non blocking style application code so don't take this the wrong way, truly trying to understand here. I'm also a little confused about threads being rescheduled by the OS being treated like an inconvenience, to me it's a feature that prevents one application being too hoggish. I can see your point that it's nice to have these labelled with await but I'm struggling to pinpoint a time I've asked myself what thread scheduling might mean for my code. Other than just assuming that another thread could be anywhere doing anything which I think is the correct approach no? Locks btw, totally non issue with the right API/Lang support.
- choochootrain 8y agoits a two-edged sword. if you can trust the application code to effectively schedule itself then it's good but you can also get bugs and perf issues where a synchronous chunk of code blocks progress on everything (see js blocking the main thread and causing the ui to freeze) the pro is that your async code explicitly defines points where context switching is okay since you're blocking on something anyways. this could be good for perf if context switching in the middle of a synchronous operation is expensive. the con is that your async code might not cede control often enough to allow other coroutines to make progress. so yes, you can have something hogging the runtime but in the context of an application that you control as a whole this is something you can avoid/fix if necessary. at the OS level this might not make sense because you have to assume that applications are adversarial and will try to hog cpu time...
- daotoad 8y agoIt's too bad Perl6's interesting approaches to concurrency aren't mentioned here. Supporting concurrency and parallelism were key points in the design of Perl6, and in the multi-paradigmatic way of Perl, it provides a variety of tools. Jonathan Worthington can write and speak about this topic far better than I can so I refer you to his talk and slides: 1. http://www.jnthn.net/papers/2018-conc-par-8-ways.pdf http://www.jnthn.net/papers/2018-conc-par-8-ways.pdf 2.C https://www.youtube.com/watch?v=l2fSbOPeSQs https://www.youtube.com/watch?v=l2fSbOPeSQs
- rurban 8y agoBut these explicitly don't mention the two best approaches he chose to ignore and even kill. First the parrot threading model, which provided lockless safe threadpools, and second the pony threading model which provides the same on top of supporting shared refs, and forbids blocking IO. Which makes it even faster. His talk ends with his simple approach taken being the best. Which is not only wrong but also a lie, because he was part in killing off the parrot threading model.
- snapdangle 8y agoReini, get off your crazy horse man! No one in the world, including the author of the Parrot threading model, thinks it is the "best" threading model.