> [Things I avoid] parking_lot: More compact and efficient implementations of the standard synchronization primitives. [goes on about efficiency...]
lol, really? No, like, not at all.
Parking lot has 1 killer feature, and 1 killer feature only, and this feature makes using the standard synchronization primitives _almost always_ the wrong choice for almost all applications:
DEADLOCK DETECTION
That's right, if you ever need a Mutex, chances are that your program might run into a deadlock at some point. Do your future self a huge favor and don't use the standard library's std::Mutex. Instead, use parking_lot::Mutex, turn on deadlock detection at compile-time, and save your future self potentially hours of trying to figure out what your program is doing, why is it deadlocking, and how to fix it.
parking_lot::Mutex panics if your program deadlocks, printing out the backtrace of each thread involved in the deadlock. This makes discovering, understanding, and fixing dead-locks a 5 minute issue, that's easily and quickly discovered during development in the minutes after introducing a deadlock bug.
I mean, you are completely right that, on top of that, parking_lot synchronization primitives are much much faster than those in the standard library. But that's only the cherry on top.
---
FWIW, nice post, I agree with all your judgements there. If you are looking for an async runtime that's smaller than tokio, check out the `smol` crate. For a thread-pool, i either just use rayon's (you can just push tasks onto its thread pool), or the futures's simple thread pool from the futures crate.
Side note: parking_lot is set to be uplifted into the standard library at some point. However it currently doesn't meet the quality standards of the standard library so more work needs to be done.
That's interesting; I imagine that they're not going to just wholesale replace std::sync::Mutex and the like with the parking lot versions due to the fact that at least last time I checked, doing that would cause breaking API changes (e.g. Mutex::lock not returning a Result, so are they planning on just making a separate module with the parking lot API as an alternative? (I supposed they could just make the parking lot Mutex return a Result that always returns Ok, but that doesn't really seem like it would appeal to most people).
Hopefully they make it a breaking change in a new edition. A little pain when updating will be much better than carrying two slightly different implementations in the long run
Cool, I didn't even know about the detection feature. When I get a deadlock, I attach a debugger and look at backtraces. So far that has always been enough for me. The nice thing is that the deadlocked threads aren't going anywhere, and wait patiently for me to inspect them :)
> The nice thing is that the deadlocked threads aren't going anywhere, and wait patiently for me to inspect them
Same opinion here. Both deadlocks and null pointer errors are fairly easy to debug. You can easily observe when exactly the happen, and the stack-trace typically delivers the answer what went wrong.
Other kind of race conditions like any memory corruptions can be such much worse to figure out.
That depends though. In Java/C# dereferencing a null reference is a runtime error and you can pinpoint exactly where it happened. In C++/Rust, dereferencing null pointers is undefined behavior since the compiler makes assumptions that a dereferenced pointer cannot be null.
If you need deadlock detection, probably your high level design is problematic. But I agree this is extremely often the case, so that's extremely often an interesting and valuable tool.
After chasing a bug for hours just to discover that it is a deadlock, its always easier to realize, in hindsight, that deadlock detection would have been useful.
Independently of how perfect your architecture is, the moment you add a Mutex to your app, you are opening the door for that to happen.
More like the moment you add a second Mutex in your app, ad-hoc handling and no policy to prevent deadlocks.
The solutions are well known and I'm simply sad to see them far too little used.
But in the case you insist in doing that (not using architectural solutions, some of which can be checked statically), yes of course runtime deadlock detection is a very valuable tool. I agree that it is even useful if you rely on policy but can't automatically check that they are respected.
I mostly agree with this except I think the bigger thing is that you should rarely be using locks in the first place. Instead use existing parallel data structures and atomics.
lol, really? No, like, not at all.
Parking lot has 1 killer feature, and 1 killer feature only, and this feature makes using the standard synchronization primitives _almost always_ the wrong choice for almost all applications:
That's right, if you ever need a Mutex, chances are that your program might run into a deadlock at some point. Do your future self a huge favor and don't use the standard library's std::Mutex. Instead, use parking_lot::Mutex, turn on deadlock detection at compile-time, and save your future self potentially hours of trying to figure out what your program is doing, why is it deadlocking, and how to fix it.parking_lot::Mutex panics if your program deadlocks, printing out the backtrace of each thread involved in the deadlock. This makes discovering, understanding, and fixing dead-locks a 5 minute issue, that's easily and quickly discovered during development in the minutes after introducing a deadlock bug.
I mean, you are completely right that, on top of that, parking_lot synchronization primitives are much much faster than those in the standard library. But that's only the cherry on top.
---
FWIW, nice post, I agree with all your judgements there. If you are looking for an async runtime that's smaller than tokio, check out the `smol` crate. For a thread-pool, i either just use rayon's (you can just push tasks onto its thread pool), or the futures's simple thread pool from the futures crate.