71 lines
1.8 KiB
C++
71 lines
1.8 KiB
C++
|
// C++11 does not support std::shared_mutex and std::shared_lock yet.
|
||
|
// This piece of Code is based on the proposal for C++14
|
||
|
#include "util/shared_mutex.h"
|
||
|
|
||
|
namespace lean {
|
||
|
shared_mutex::shared_mutex():m_state(0) {}
|
||
|
shared_mutex::~shared_mutex() {
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
}
|
||
|
|
||
|
void shared_mutex::lock() {
|
||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||
|
while (m_state & write_entered)
|
||
|
m_gate1.wait(lock);
|
||
|
m_state |= write_entered;
|
||
|
while (m_state & readers)
|
||
|
m_gate2.wait(lock);
|
||
|
}
|
||
|
|
||
|
bool shared_mutex::try_lock() {
|
||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||
|
if (m_state == 0) {
|
||
|
m_state = write_entered;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void shared_mutex::unlock() {
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
m_state = 0;
|
||
|
m_gate1.notify_all();
|
||
|
}
|
||
|
|
||
|
void shared_mutex::lock_shared() {
|
||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||
|
while ((m_state & write_entered) || (m_state & readers) == readers)
|
||
|
m_gate1.wait(lock);
|
||
|
unsigned num_readers = (m_state & readers) + 1;
|
||
|
m_state &= ~readers;
|
||
|
m_state |= num_readers;
|
||
|
}
|
||
|
|
||
|
bool shared_mutex::try_lock_shared()
|
||
|
{
|
||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||
|
unsigned num_readers = m_state & readers;
|
||
|
if (!(m_state & write_entered) && num_readers != readers) {
|
||
|
++num_readers;
|
||
|
m_state &= ~readers;
|
||
|
m_state |= num_readers;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void shared_mutex::unlock_shared() {
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
unsigned num_readers = (m_state & readers) - 1;
|
||
|
m_state &= ~readers;
|
||
|
m_state |= num_readers;
|
||
|
if (m_state & write_entered) {
|
||
|
if (num_readers == 0)
|
||
|
m_gate2.notify_one();
|
||
|
} else {
|
||
|
if (num_readers == readers - 1)
|
||
|
m_gate1.notify_one();
|
||
|
}
|
||
|
}
|
||
|
}
|