1
0
mirror of https://github.com/Zygo/bees.git synced 2025-05-17 21:35:45 +02:00

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 <bees@furryterror.org>
This commit is contained in:
Zygo Blaxell 2017-01-09 23:23:51 -05:00
parent fa8607bae0
commit bda4638048

View File

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