Skip to content
Permalink
Browse files

Make LOCK, LOCK2, TRY_LOCK work with CWaitableCriticalSection

They should also work with any other mutex type which std::unique_lock
supports.

There is no change in behavior for current code that calls these macros with
CCriticalSection mutexes.
  • Loading branch information...
ryanofsky committed Nov 8, 2017
1 parent d7d17bb commit 5938e5482de24cda6e48ff1ce0797e6e2478f9d5
Showing with 34 additions and 12 deletions.
  1. +19 −8 src/sync.h
  2. +15 −4 src/test/sync_tests.cpp
@@ -111,11 +111,12 @@ typedef std::unique_lock<std::mutex> WaitableLock;
void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
#endif

/** Wrapper around std::unique_lock<CCriticalSection> */
/** Wrapper around std::unique_lock<Mutex> */
template <typename Mutex>
class SCOPED_LOCKABLE CCriticalBlock
{
private:
std::unique_lock<CCriticalSection> lock;
std::unique_lock<Mutex> lock;

void Enter(const char* pszName, const char* pszFile, int nLine)
{
@@ -140,19 +141,19 @@ class SCOPED_LOCKABLE CCriticalBlock
}

public:
CCriticalBlock(CCriticalSection& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : lock(mutexIn, std::defer_lock)
CCriticalBlock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : lock(mutexIn, std::defer_lock)
{
if (fTry)
TryEnter(pszName, pszFile, nLine);
else
Enter(pszName, pszFile, nLine);
}

CCriticalBlock(CCriticalSection* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
CCriticalBlock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
{
if (!pmutexIn) return;

lock = std::unique_lock<CCriticalSection>(*pmutexIn, std::defer_lock);
lock = std::unique_lock<Mutex>(*pmutexIn, std::defer_lock);
if (fTry)
TryEnter(pszName, pszFile, nLine);
else
@@ -171,12 +172,22 @@ class SCOPED_LOCKABLE CCriticalBlock
}
};

template <typename MutexArg, typename... Args>
CCriticalBlock<typename std::remove_reference<typename std::remove_pointer<MutexArg>::type>::type> DebugLock(
MutexArg&& mutex,
Args&&... args)
{
return {std::forward<MutexArg>(mutex), std::forward<Args>(args)...};
}

#define PASTE(x, y) x ## y
#define PASTE2(x, y) PASTE(x, y)

#define LOCK(cs) CCriticalBlock PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, __LINE__)
#define LOCK2(cs1, cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__), criticalblock2(cs2, #cs2, __FILE__, __LINE__)
#define TRY_LOCK(cs, name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true)
#define LOCK(cs) auto&& PASTE2(criticalblock, __COUNTER__) = DebugLock(cs, #cs, __FILE__, __LINE__)
#define LOCK2(cs1, cs2) \
auto&& criticalblock1 = DebugLock(cs1, #cs1, __FILE__, __LINE__); \
auto&& criticalblock2 = DebugLock(cs2, #cs2, __FILE__, __LINE__);
#define TRY_LOCK(cs, name) auto&& name = DebugLock(cs, #cs, __FILE__, __LINE__, true)

#define ENTER_CRITICAL_SECTION(cs) \
{ \
@@ -7,11 +7,10 @@

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(sync_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(potential_deadlock_detected)
namespace {
template <typename MutexType>
void TestPotentialDeadLockDetected(MutexType& mutex1, MutexType& mutex2)
{
CCriticalSection mutex1, mutex2;
{
LOCK2(mutex1, mutex2);
}
@@ -26,5 +25,17 @@ BOOST_AUTO_TEST_CASE(potential_deadlock_detected)
BOOST_CHECK(error_thrown);
#endif
}
} // namespace

BOOST_FIXTURE_TEST_SUITE(sync_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(potential_deadlock_detected)
{
CCriticalSection rmutex1, rmutex2;
TestPotentialDeadLockDetected(rmutex1, rmutex2);

CWaitableCriticalSection mutex1, mutex2;
TestPotentialDeadLockDetected(mutex1, mutex2);
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 5938e54

Please sign in to comment.
You can’t perform that action at this time.