That is similar how the STL does it, but not like stdio
I'm not sure I fully agree.
- For simple libraries it's likely good advice.
- But it encourages big locks and poor scaling. It may be right for desktop apps, but not necessarily for server code that needs to scale. For some things that's fine, but you don't want that for the big tree or hash table that your multi threaded server is built around on.
- It avoids the problems of locks being non composable, that is the caller may need to know which order the locks need to be called, to avoid deadlock. Actually it doesn't avoid it, just pushes it to someone else.
However if you make sure the library is always the leaf and never calls back the library locks will be generally at the bottom of the lock hierarchy.
Let's be honest. Most multithreaded programs evolve from programs that are more-or-less single threaded. Then, threads are added in an attempt to improve performance, and high-contention locks are broken into finer grained locks when profiling shows lock contention in the critical path. I would argue it's better to either design for minimal mutable global state from the start. Failing that, it's often better to re-factor the code when you start scaling up the number of threads, before you start investing a lot of time into locking and breaking down your big locks into finer and finer grained locks.
I'm sure you're not one of those programmers who often leans on mutexes/semaphores/etc. as a crutch to prop up poor design, but there are a lot of programmers who do.