From 4f66d1cb44948e1c5d96911145b191e2cd27ede1 Mon Sep 17 00:00:00 2001 From: Zygo Blaxell Date: Thu, 30 Mar 2017 00:35:59 -0400 Subject: [PATCH] crucible: lockset: track lockers and use handle type [bees master branch edition] Keep track of the locking thread so we can see why we are deadlocked in gdb. Use a handle type for locks based on shared_ptr. Change the handle type name to flush out any non-auto local variables. Signed-off-by: Zygo Blaxell (cherry picked from commit aa0b22d445664409c36503c6fd808bc49b6816d0) --- include/crucible/lockset.h | 72 ++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/include/crucible/lockset.h b/include/crucible/lockset.h index 2af782d..e792e9d 100644 --- a/include/crucible/lockset.h +++ b/include/crucible/lockset.h @@ -2,14 +2,16 @@ #define CRUCIBLE_LOCKSET_H #include +#include #include #include #include #include +#include +#include #include -#include namespace crucible { using namespace std; @@ -18,7 +20,7 @@ namespace crucible { class LockSet { public: - using set_type = set; + using set_type = map; using key_type = typename set_type::key_type; private: @@ -31,6 +33,24 @@ namespace crucible { bool full(); bool locked(const key_type &name); + class Lock { + LockSet &m_lockset; + key_type m_name; + bool m_locked; + + Lock() = delete; + Lock(const Lock &) = delete; + Lock& operator=(const Lock &) = delete; + Lock(Lock &&that) = delete; + Lock& operator=(Lock &&that) = delete; + public: + ~Lock(); + Lock(LockSet &lockset, const key_type &name, bool start_locked = true); + void lock(); + void unlock(); + bool try_lock(); + }; + public: ~LockSet(); LockSet() = default; @@ -45,24 +65,18 @@ namespace crucible { void max_size(size_t max); - class Lock { - LockSet &m_lockset; - key_type m_name; - bool m_locked; + class LockHandle { + shared_ptr m_lock; - Lock() = delete; - Lock(const Lock &) = delete; - Lock& operator=(const Lock &) = delete; public: - ~Lock(); - Lock(LockSet &lockset, const key_type &m_name, bool start_locked = true); - Lock(Lock &&that); - Lock& operator=(Lock &&that); - void lock(); - void unlock(); - bool try_lock(); + LockHandle(LockSet &lockset, const key_type &name, bool start_locked = true) : + m_lock(make_shared(lockset, name, start_locked)) {} + void lock() { m_lock->lock(); } + void unlock() { m_lock->unlock(); } + bool try_lock() { return m_lock->try_lock(); } }; + LockHandle make_lock(const key_type &name, bool start_locked = true); }; template @@ -104,7 +118,7 @@ namespace crucible { while (full() || locked(name)) { m_condvar.wait(lock); } - auto rv = m_set.insert(name); + auto rv = m_set.insert(make_pair(name, gettid())); THROW_CHECK0(runtime_error, rv.second); } @@ -116,7 +130,7 @@ namespace crucible { if (full() || locked(name)) { return false; } - auto rv = m_set.insert(name); + auto rv = m_set.insert(make_pair(name, gettid())); THROW_CHECK1(runtime_error, name, rv.second); return true; } @@ -214,26 +228,10 @@ namespace crucible { } template - LockSet::Lock::Lock(Lock &&that) : - m_lockset(that.lockset), - m_name(that.m_name), - m_locked(that.m_locked) + typename LockSet::LockHandle + LockSet::make_lock(const key_type &name, bool start_locked) { - that.m_locked = false; - } - - template - typename LockSet::Lock & - LockSet::Lock::operator=(Lock &&that) - { - THROW_CHECK2(invalid_argument, &m_lockset, &that.m_lockset, &m_lockset == &that.m_lockset); - if (m_locked && that.m_name != m_name) { - unlock(); - } - m_name = that.m_name; - m_locked = that.m_locked; - that.m_locked = false; - return *this; + return LockHandle(*this, name, start_locked); } }