mirror of
https://github.com/Zygo/bees.git
synced 2025-05-17 21:35:45 +02:00
Add a master switch to turn off the entire MultiLock infrastructure for testing, without having to remove and add all the individual entry points. Signed-off-by: Zygo Blaxell <bees@furryterror.org>
84 lines
1.6 KiB
C++
84 lines
1.6 KiB
C++
#include "crucible/multilock.h"
|
|
|
|
#include "crucible/error.h"
|
|
|
|
namespace crucible {
|
|
using namespace std;
|
|
|
|
MultiLocker::LockHandle::LockHandle(const string &type, MultiLocker &parent) :
|
|
m_type(type),
|
|
m_parent(parent)
|
|
{
|
|
}
|
|
|
|
void
|
|
MultiLocker::LockHandle::set_locked(const bool state)
|
|
{
|
|
m_locked = state;
|
|
}
|
|
|
|
MultiLocker::LockHandle::~LockHandle()
|
|
{
|
|
if (m_locked) {
|
|
m_parent.put_lock(m_type);
|
|
m_locked = false;
|
|
}
|
|
}
|
|
|
|
bool
|
|
MultiLocker::is_lock_available(const string &type)
|
|
{
|
|
for (const auto &i : m_counters) {
|
|
if (i.second != 0 && i.first != type) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void
|
|
MultiLocker::put_lock(const string &type)
|
|
{
|
|
unique_lock<mutex> lock(m_mutex);
|
|
auto &counter = m_counters[type];
|
|
THROW_CHECK2(runtime_error, type, counter, counter > 0);
|
|
--counter;
|
|
if (counter == 0) {
|
|
m_cv.notify_all();
|
|
}
|
|
}
|
|
|
|
shared_ptr<MultiLocker::LockHandle>
|
|
MultiLocker::get_lock_private(const string &type)
|
|
{
|
|
unique_lock<mutex> lock(m_mutex);
|
|
m_counters.insert(make_pair(type, size_t(0)));
|
|
while (!is_lock_available(type)) {
|
|
m_cv.wait(lock);
|
|
}
|
|
const auto rv = make_shared<LockHandle>(type, *this);
|
|
++m_counters[type];
|
|
rv->set_locked(true);
|
|
return rv;
|
|
}
|
|
|
|
static MultiLocker s_process_instance;
|
|
|
|
shared_ptr<MultiLocker::LockHandle>
|
|
MultiLocker::get_lock(const string &type)
|
|
{
|
|
if (s_process_instance.m_do_locking) {
|
|
return s_process_instance.get_lock_private(type);
|
|
} else {
|
|
return shared_ptr<MultiLocker::LockHandle>();
|
|
}
|
|
}
|
|
|
|
void
|
|
MultiLocker::enable_locking(const bool enabled)
|
|
{
|
|
s_process_instance.m_do_locking = enabled;
|
|
}
|
|
|
|
}
|