5 ms·
The snide response to this is does anything in C++ spark joy? More seriously, I've come to believe that most people shouldn't be writing multithreaded code. Mo
by cletus 5y ago
The snide response to this is does anything in C++ spark joy?
More seriously, I've come to believe that most people shouldn't be writing multithreaded code. More specifically, if you ever find yourself instantiating a thread directly you've probably made a mistake. It's possible you're writing something sufficiently low-level or a library or framework that justifies that of course.
From using Hack, I've come to really appreciate the single-threaded cooperative multitasking programming model for client code [1]. It's not unique to Hack obviously.
Part of the power of C++ is the ability to allocate things on the stack or the heap. This is powerful but the complexity cost of this is so incredibly high that I honestly question if it's worth it.
It's unsurprising to me to see the complexity that comes with coroutines as a result of this.
[1]: https://docs.hhvm.com/hack/asynchronous-operations/introduction https://docs.hhvm.com/hack/asynchronous-operations/introduct...
- jeffbee 5y agoIs it that complicated? std::thread t([](){ std::cout << "thread function\n"; }); t.join(); With sane ground rules threading is not so hard. Don't try to use subtle atomics. Do use a mutex to protect all shared state. Do use scoped locks. Do use thread safety annotations.
- liuliu 5y agoThe difficulties of multi-threading code to me is not about crashes or protecting shared states or ownerships. It is about reasoning how it might interleaving between these protected critical sections. For these, mutexes / locks / atomics are the wrong level of abstractions to reason about on daily basis. I haven't used Structured Concurrency long enough to form an opinion whether that is the right level of abstraction or not.
- Jtsummers 5y agoStructured concurrency only partially helps. You still have to be aware of what state is being used and modified within the threads of execution so that you properly lock them. It does not remove the need for some equivalent to mutexes and locks unless each thread of execution is known to use and modify different pieces of state (like thread 0 modifies a[0], 1 modifies a[1], etc.). If there's any overlap you have to have a lock-equivalent that ensures the desired section of code runs atomically (relative to others using the same pieces of state). Or you need some kind of transaction system that can retry a stateful change.
- liuliu 5y agoIt is ... complicated when talking in the context of "threads modifying states". I am more thinking through "shared states" needs to be published after exiting a critical section [1], and other states are passed along from one critical section to another (either as copyable values, or immutable state objects). At least this is the easiest for me at the moment to reason about a piece of concurrency code. [1] I am using critical section here to loosely describe a block of code needs to be executed together. It can be code between two yield points (in coroutine), a "task" object (in traditional task based scheduling), or section of code protected by a mutex.
- physicsguy 5y agoI personally prefer OpenMP to other threading models, but I come from a scientific programming background. Very simple (or at least it was til accelerators came along), same in C/C++/Fortran.