cpprefjpでstd::recursive_mutexのリファレンスを書いていて実装が気になったので、Boost.Threadにあるrecursive_mutexの実装を見てました。
実装のポイントは以下の2点でした:
1. すでにロックされている場合、スレッドIDをチェックして同じだったら再度ロック処理はしない
2. 現在ロックが取得されているスレッドでの、ロックされている数をカウントし、0になったときにアンロックする
以下、std::mutexをベースにした簡易実装です:
#include <iostream> #include <mutex> #include <thread> #include <boost/optional.hpp> class recursive_mutex { std::mutex inner_mtx_; std::size_t lock_count_ = 0; boost::optional<std::thread::id> thread_id_; public: void lock() { std::thread::id id = std::this_thread::get_id(); if (lock_count_ == 0 || thread_id_.get() != id) { inner_mtx_.lock(); thread_id_ = id; } ++lock_count_; } void unlock() { std::thread::id id = std::this_thread::get_id(); if (thread_id_.get() != id) return; if (--lock_count_ == 0) { inner_mtx_.unlock(); thread_id_ = boost::none; } } }; int main() { std::cout << "start" << std::endl; ::recursive_mutex mtx; mtx.lock(); { mtx.lock(); mtx.unlock(); } mtx.unlock(); std::cout << "end" << std::endl; }
start end
# 飽くまで実装イメージですので、本気実装がほしい方は標準やBoostのを使ってください。