@@ -244,12 +244,26 @@ class SCOPED_LOCKABLE UniqueLock : public Base
244
244
template<typename MutexArg>
245
245
using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove_pointer<MutexArg>::type>::type>;
246
246
247
- #define LOCK (cs ) DebugLock<decltype (cs)> UNIQUE_NAME (criticalblock)(cs, #cs, __FILE__, __LINE__)
247
+ // When locking a Mutex, require negative capability to ensure the lock
248
+ // is not already held
249
+ inline Mutex& MaybeCheckNotHeld (Mutex& cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; }
250
+ inline Mutex* MaybeCheckNotHeld (Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; }
251
+
252
+ // When locking a GlobalMutex, just check it is not locked in the surrounding scope
253
+ inline GlobalMutex& MaybeCheckNotHeld (GlobalMutex& cs) LOCKS_EXCLUDED(cs) LOCK_RETURNED(cs) { return cs; }
254
+ inline GlobalMutex* MaybeCheckNotHeld (GlobalMutex* cs) LOCKS_EXCLUDED(cs) LOCK_RETURNED(cs) { return cs; }
255
+
256
+ // When locking a RecursiveMutex, it's okay to already hold the lock
257
+ // but check that it is not known to be locked in the surrounding scope anyway
258
+ inline RecursiveMutex& MaybeCheckNotHeld (RecursiveMutex& cs) LOCKS_EXCLUDED(cs) LOCK_RETURNED(cs) { return cs; }
259
+ inline RecursiveMutex* MaybeCheckNotHeld (RecursiveMutex* cs) LOCKS_EXCLUDED(cs) LOCK_RETURNED(cs) { return cs; }
260
+
261
+ #define LOCK (cs ) DebugLock<decltype (cs)> UNIQUE_NAME (criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
248
262
#define LOCK2 (cs1, cs2 ) \
249
- DebugLock<decltype (cs1)> criticalblock1 (cs1, #cs1, __FILE__, __LINE__); \
250
- DebugLock<decltype (cs2)> criticalblock2 (cs2, #cs2, __FILE__, __LINE__);
251
- #define TRY_LOCK (cs, name ) DebugLock<decltype (cs)> name (cs , #cs, __FILE__, __LINE__, true )
252
- #define WAIT_LOCK (cs, name ) DebugLock<decltype (cs)> name (cs , #cs, __FILE__, __LINE__)
263
+ DebugLock<decltype (cs1)> criticalblock1 (MaybeCheckNotHeld( cs1) , #cs1, __FILE__, __LINE__); \
264
+ DebugLock<decltype (cs2)> criticalblock2 (MaybeCheckNotHeld( cs2) , #cs2, __FILE__, __LINE__);
265
+ #define TRY_LOCK (cs, name ) DebugLock<decltype (cs)> name (MaybeCheckNotHeld(cs) , #cs, __FILE__, __LINE__, true )
266
+ #define WAIT_LOCK (cs, name ) DebugLock<decltype (cs)> name (MaybeCheckNotHeld(cs) , #cs, __FILE__, __LINE__)
253
267
254
268
#define ENTER_CRITICAL_SECTION (cs ) \
255
269
{ \
@@ -288,7 +302,7 @@ using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove
288
302
// !
289
303
// ! The above is detectable at compile-time with the -Wreturn-local-addr flag in
290
304
// ! gcc and the -Wreturn-stack-address flag in clang, both enabled by default.
291
- #define WITH_LOCK (cs, code ) [&]() -> decltype (auto ) { LOCK (cs); code; }()
305
+ #define WITH_LOCK (cs, code ) (MaybeCheckNotHeld(cs), [&]() -> decltype (auto ) { LOCK (cs); code; }() )
292
306
293
307
class CSemaphore
294
308
{
0 commit comments