naive fair mutex implementation (with recursive semantics)
#include <cassert> | |
#include <queue> | |
#include <condition_variable> | |
#include <mutex> | |
#include <thread> | |
class fair_recursive_mutex { | |
std::mutex mtx_; | |
std::condition_variable cv_; | |
std::queue<std::thread::id> q_; | |
unsigned int count_; | |
public: | |
fair_recursive_mutex() : count_(0) {} | |
~fair_recursive_mutex() = default; | |
fair_recursive_mutex(const fair_recursive_mutex&) = delete; | |
fair_recursive_mutex& operator=(const fair_recursive_mutex&) = delete; | |
void lock() | |
{ | |
const std::thread::id tid = std::this_thread::get_id(); | |
std::unique_lock<decltype(mtx_)> lk(mtx_); | |
if (!q_.empty() && q_.front() != tid) | |
cv_.wait(lk, [&]{ return q_.empty(); }); | |
if (q_.empty()) | |
q_.push(tid); | |
++count_; | |
assert(q_.front() == tid); | |
} | |
bool try_lock() | |
{ | |
const std::thread::id tid = std::this_thread::get_id(); | |
std::lock_guard<decltype(mtx_)> lk(mtx_); | |
if (!q_.empty() && q_.front() != tid) | |
return false; | |
if (q_.empty()) | |
q_.push(tid); | |
++count_; | |
assert(q_.front() == tid); | |
return true; | |
} | |
void unlock() | |
{ | |
std::lock_guard<decltype(mtx_)> lk(mtx_); | |
assert(q_.front() == std::this_thread::get_id()); | |
if (--count_ == 0) { | |
q_.pop(); | |
cv_.notify_all(); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment