mirror of
https://github.com/Zygo/bees.git
synced 2025-05-17 21:35:45 +02:00
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 <bees@furryterror.org> (cherry picked from commit aa0b22d445664409c36503c6fd808bc49b6816d0)
This commit is contained in:
parent
3901962379
commit
4f66d1cb44
@ -2,14 +2,16 @@
|
||||
#define CRUCIBLE_LOCKSET_H
|
||||
|
||||
#include <crucible/error.h>
|
||||
#include <crucible/process.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
|
||||
namespace crucible {
|
||||
using namespace std;
|
||||
@ -18,7 +20,7 @@ namespace crucible {
|
||||
class LockSet {
|
||||
|
||||
public:
|
||||
using set_type = set<T>;
|
||||
using set_type = map<T, pid_t>;
|
||||
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<Lock> 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<Lock>(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 <class T>
|
||||
@ -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 <class T>
|
||||
LockSet<T>::Lock::Lock(Lock &&that) :
|
||||
m_lockset(that.lockset),
|
||||
m_name(that.m_name),
|
||||
m_locked(that.m_locked)
|
||||
typename LockSet<T>::LockHandle
|
||||
LockSet<T>::make_lock(const key_type &name, bool start_locked)
|
||||
{
|
||||
that.m_locked = false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename LockSet<T>::Lock &
|
||||
LockSet<T>::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);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user