C/C++: (avoid) Asserting that a Lock is Taken

July 29, 2013

Readers asked about lock state assertion. Here goes my recommendation: avoid it. Locks are structures meant to protect critical regions. If we are inside one, a lock assertion isn’t necessary.

But what about outside critical region checks?”, they insist. Well, I believe that’s the kind o thinking that leads to race-conditions. If we are outside a critical region, asserting that a lock is [not] taken should be unnecessary, generating only noise.

Besides having little or no reason for implementing such logic, people sometimes make bad choices regarding lock debugging code. One I’ve seen is holding a mutex whose state is supposed to be verified, and then release it. The result: at the time the check returns, the mutex in question may or may not be taken by other tasks/threads (exactly what was known before inspection).

Functions like TryEnterCriticalSection() (or pthread_mutex_trylock()) are common suggestions for lock assertion optimization. They remind “The Best Optimizer is between Your Ears“, from Michael Abrash, where he talks about “fast slow code” (the difference is that we have “fast wrong/useless code” here). It doesn’t matter. There’s an insidious side effect with this whole concept: debug builds become even less scalable than release ones. And we all know that more differences between build types make testing/QA harder.

The desire to assert that a lock is taken often signals an architectural trait misunderstanding. Instead, try to focus on asserting the integrity of more important data structures (usually, the ones protected by the locks themselves).