Skip to content

Instantly share code, notes, and snippets.

@yohhoy
Last active December 19, 2015 19:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yohhoy/6009707 to your computer and use it in GitHub Desktop.
Save yohhoy/6009707 to your computer and use it in GitHub Desktop.
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