Malte Skarupke writes about C++ performance, hash tables, data structures, and debugging low-level concurrency problems.
Commenters call his posts great reads and point to his hash table and min-max heap articles, including graphs that undermine the idea of constant-time lookups.
That is even more hilariously hand-wavey, given you just got smoked for that.
Fail-safe systems are notoriously hard to design - what is the truth when one system is wrong? How do you detect that a system is giving the wrong answer (737MAX hardware sensor failure, software working exactly as very carefully designed)? Adding complexity decreases reliability unless some very deep voodoo engineering is applied.
I think you are thinking linearly, that two systems with a 1% failure rate could be put together to make a system with 0.01% failure rate. Bzzzzzzt, wrong, instead you could easily end up with a system with a 5% failure rate.
There are many sources of confounding variables: two systems tend to fail in the same complex corner cases, safety systems tend to have common dependencies (Fukushima tidal wave), and adding complexity to systems adds subtle failure modes.
Disclaimer: I would call myself a software engineer, because my definition of engineering is making good compromises. Other “engineering” disciplines very often work on non-safety critical systems, yet they are still called engineers. And these days software underpins most safety critical systems e.g. you depend somewhat that your CAD software or circuit analysis software returns the correct result, even though software usually disclaims all warranties/guarantees. The designers of the space-shuttle made safety compromises, but that was engineering. SpaceX followed a fail-fast approach, and I think software…
I would venture a guess to say that what makes FP or declarative style programming/thinking feel weird is not any great context like the nature of the human brain but rather the lesser one that usually people try to learn it after already having had learned imperative style stuff.
The functionally written recipe from https://probablydance.com/2016/02/27/functional-programming-is-not-popular-because-it-is-weird/ may be less helpful if I need to know exactly what steps to take to bake a cake, but it will actually be much more helpful if I want to know what a baked cake is. It isn't quite a fair example because it leverages how humans already know what a baked cake is, what a preheated oven is, etc and the clunkiness of the FP-style recipe is likely more due to that than anything fundamental to FP.
Let's try a different example that better maps to real world application logic. The task is to build a scootybooty.
Imperatively, a scootybooty program is:
- Acquire four wheels and two axels.
- Chop down a tree.
- Plane wood from tree into curved flat shape.
- Attach axels to convex side of planed wood shape.
- Attach wheels to axel.
Declaratively it is:
- A scootybooty is a planed plank of wood with two trucks.
- A planed plank of wood is a flat board.
- A truck is an axel with two wheels.
Now imagine your boss asks you wtf this scootybooty thing is and what it can do. Which program more quickly allows you to answer these questions? My favorite thing about the…
Weave is my multithreading library. It's just a recap of what I went through for future reference.
I unfortunately didn't have time to go through:
- compiling glibc from source
- converting my code to C
- trying to reduce multithreaded synchronization code to a minimal example given how non-deterministic any of those bugs are
- do a write-up
That said, it seems like people went through the motions 4 months after me in this bug:
- https://sourceware.org/bugzilla/show_bug.cgi?id=25847 which affects C#, OCaml, Python
Someone also fully reimplemented Glibc condition variable in TLA+ to prove that the glibc code was buggy:
- https://probablydance.com/2020/10/31/using-tla-in-the-real-world-to-understand-a-glibc-bug/ (at the bottom)
> personally I find my brain works very much like a Turing Machine
Exactly this. How baking a cake in FP looks like:
* A cake is a hot cake that has been cooled on a damp tea towel, where a hot cake is a prepared cake that has been baked in a preheated oven for 30 minutes.
* A preheated oven is an oven that has been heated to 175 degrees C.
* A prepared cake is batter that has been poured into prepared pans, where batter is mixture that has chopped walnuts stirred in. Where mixture is butter, white sugar and brown sugar that has been creamed in a large bowl until light and fluffy
Taken from here:
https://probablydance.com/2016/02/27/functional-programming-is-not-popular-because-it-is-weird/
> some kind of bucket-optimisation (multiple elements per allocation, instead of one element per allocation) should also meet all constraints the standard sets for this type
Pretty sure that makes it impossible to implement merge without pointer/iterator invalidation, which is a constraint imposed by the standard (https://en.cppreference.com/w/cpp/container/unordered_map/merge).
> it would be good if the person I originally responded to came out and defended his POV
See https://probablydance.com/2017/02/26/i-wrote-the-fastest-hashtable/ if you want numbers, or for example this talk by the same author https://www.youtube.com/watch?v=M2fKMP47slQ.
It's exactly what it says, it's a coroutine with its own stack.
A fiber isn't to some degree a stackful coroutine, it is a stackful coroutine.
A stackless coroutine does not have a its own stack, it uses the calling context's stack and therefore can only yield to the calling context from the top-level coroutine function. A stackful coroutine has its own stack, and so can yield to the calling context from anywhere.
As far as how to implement, I always liked Malte Skarupke's blog post on the subject: https://probablydance.com/2013/02/20/handmade-coroutines-for-windows/