From bda4638048e94e9e39ee2e67b66238097624320a Mon Sep 17 00:00:00 2001 From: Zygo Blaxell Date: Mon, 9 Jan 2017 23:23:51 -0500 Subject: [PATCH] crucible: LockSet: add a maximum size constraint Extend the LockSet class so that the total number of locked (active) items can be limited. When the limit is reached, no new items can be locked until some existing locked items are unlocked. Signed-off-by: Zygo Blaxell --- include/crucible/lockset.h | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) 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); }