mutex.cpp: minor update

New concept (incomplete)
This commit is contained in:
Nekotekina 2017-10-05 15:09:08 +03:00
parent 3907dd0444
commit beab5291bb
2 changed files with 141 additions and 1 deletions

View file

@ -1,7 +1,12 @@
#include "mutex.h"
#include "sync.h"
#include <limits.h>
#include <climits>
#include <vector>
#include <algorithm>
// TLS variable for tracking owned mutexes
thread_local std::vector<shared_mutex*> g_tls_locks;
void shared_mutex::imp_lock_shared(s64 _old)
{
@ -217,12 +222,14 @@ void shared_mutex::imp_unlock(s64 _old)
void shared_mutex::imp_lock_upgrade()
{
// TODO
unlock_shared();
lock();
}
void shared_mutex::imp_lock_degrade()
{
// TODO
unlock();
lock_shared();
}
@ -250,3 +257,78 @@ bool shared_mutex::try_lock_degrade()
// TODO
return m_value.compare_and_swap_test(0, c_one - c_min);
}
safe_reader_lock::safe_reader_lock(shared_mutex& mutex)
: m_mutex(mutex)
, m_is_owned(false)
{
if (std::count(g_tls_locks.cbegin(), g_tls_locks.cend(), &m_mutex) == 0)
{
m_is_owned = true;
if (m_is_owned)
{
m_mutex.lock_shared();
g_tls_locks.emplace_back(&m_mutex);
return;
}
// TODO: order locks
}
}
safe_reader_lock::~safe_reader_lock()
{
if (m_is_owned)
{
m_mutex.unlock_shared();
g_tls_locks.erase(std::remove(g_tls_locks.begin(), g_tls_locks.end(), &m_mutex), g_tls_locks.cend());
return;
}
// TODO: order locks
}
safe_writer_lock::safe_writer_lock(shared_mutex& mutex)
: m_mutex(mutex)
, m_is_owned(false)
, m_is_upgraded(false)
{
if (std::count(g_tls_locks.cbegin(), g_tls_locks.cend(), &m_mutex) == 0)
{
m_is_owned = true;
if (m_is_owned)
{
m_mutex.lock_shared();
g_tls_locks.emplace_back(&m_mutex);
return;
}
// TODO: order locks
}
if (m_mutex.is_reading())
{
m_is_upgraded = true;
m_mutex.lock_upgrade();
}
}
safe_writer_lock::~safe_writer_lock()
{
if (m_is_upgraded)
{
m_mutex.lock_degrade();
return;
}
if (m_is_owned)
{
m_mutex.unlock();
g_tls_locks.erase(std::remove(g_tls_locks.begin(), g_tls_locks.end(), &m_mutex), g_tls_locks.cend());
return;
}
// TODO: order locks
}

View file

@ -95,6 +95,11 @@ public:
imp_lock_degrade();
}
}
bool is_reading() const
{
return (m_value.load() % c_one) != 0;
}
};
// Simplified shared (reader) lock implementation.
@ -171,3 +176,56 @@ public:
unlock();
}
};
// Safe reader lock. Can be recursive above other safe locks (reader or writer).
class safe_reader_lock final
{
shared_mutex& m_mutex;
bool m_is_owned;
void lock()
{
m_mutex.lock_shared();
}
void unlock()
{
m_mutex.unlock_shared();
}
friend class cond_variable;
public:
safe_reader_lock(const safe_reader_lock&) = delete;
explicit safe_reader_lock(shared_mutex& mutex);
~safe_reader_lock();
};
// Safe writer lock. Can be recursive above other safe locks. Performs upgrade and degrade operations above existing reader lock if necessary.
class safe_writer_lock final
{
shared_mutex& m_mutex;
bool m_is_owned;
bool m_is_upgraded;
void lock()
{
m_mutex.lock();
}
void unlock()
{
m_mutex.unlock();
}
friend class cond_variable;
public:
safe_writer_lock(const safe_writer_lock&) = delete;
explicit safe_writer_lock(shared_mutex& mutex);
~safe_writer_lock();
};