diff --git a/include/crucible/lockset.h b/include/crucible/lockset.h index 0524f7f..dcf82f2 100644 --- a/include/crucible/lockset.h +++ b/include/crucible/lockset.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -17,14 +18,18 @@ namespace crucible { class LockSet { public: - using key_type = T; using set_type = set; + using key_type = typename set_type::key_type; private: set_type m_set; mutex m_mutex; condition_variable m_condvar; + size_t m_max_size = numeric_limits::max(); + + bool full(); + bool locked(const key_type &name); public: ~LockSet(); @@ -38,6 +43,8 @@ namespace crucible { set_type copy(); void wait_unlock(double interval); + void max_size(size_t max); + class Lock { LockSet &m_lockset; key_type m_name; @@ -68,12 +75,33 @@ namespace crucible { assert(m_set.empty()); } + template + bool + LockSet::full() + { + return m_set.size() >= m_max_size; + } + + template + bool + LockSet::locked(const key_type &name) + { + return m_set.count(name); + } + + template + void + LockSet::max_size(size_t s) + { + m_max_size = s; + } + template void LockSet::lock(const key_type &name) { unique_lock lock(m_mutex); - while (m_set.count(name)) { + while (full() || locked(name)) { m_condvar.wait(lock); } auto rv = m_set.insert(name); @@ -85,7 +113,7 @@ namespace crucible { LockSet::try_lock(const key_type &name) { unique_lock lock(m_mutex); - if (m_set.count(name)) { + if (full() || locked(name)) { return false; } auto rv = m_set.insert(name); @@ -98,8 +126,8 @@ namespace crucible { LockSet::unlock(const key_type &name) { unique_lock lock(m_mutex); - m_condvar.notify_all(); auto erase_count = m_set.erase(name); + m_condvar.notify_all(); THROW_CHECK1(invalid_argument, erase_count, erase_count == 1); }