Some people are warning that locks can be mis-used by writing:
std::unique_lock<std::mutex>(mutex);
instead of the following correct statement:
std::unique_lock<std::mutex> lock(mutex);
I.e. create an unnamed temporary variable instead of a local variable. The temporary variable would be destroyed immediately and unlock the mutex prematurely.
See for instance gperftools (line 321-324) header:
// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
This macro is written to protect again such use cases.
But can it still happen? Apparently a recent enough GCC or clang will produce errors in this case:
#include <iostream>
class Mutex {};
class Lock {
public:
explicit Lock(Mutex */* dummy */) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
~Lock() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
int main() {
Mutex mutex;
{
Lock l(&mutex);
}
{
Lock(&mutex); // This line does not compile.
}
return 0;
}
And the error:
g++ foo.cpp
foo.cpp:17:11: error: declaration of reference variable 'mutex' requires an initializer
Lock(&mutex);
^~~~~
1 error generated.
Could someone exhibit a repro case where such a macro would catch a real bug? I could not come up with one so far.