C++11標準ライブラリを用いた再帰ミューテックスrecursive_mutex
クラスの内部実装 3パターン。標準ライブラリが提供するstd::recursive_mutex
の再実装。
各実装で利用している同期プリミティブ
- #1:
std::mutex
+std::condition_variable
- #2: 2個の
std::mutex
- #3:
std::atomic
+std::mutex
メモ:
std::thread::id
クラスのコンストラクタが非constexprなため、recursive_mutex
クラスのコンストラクタをconstexprにできず。(標準ライブラリ提供のstd::recursive_mutex
も非constexprコンストラクタを持つ→id:yohhoy:20120621)#3は全部全てstd::memory_order_relaxed
でも良いような?relaxed
操作でも標準ライブラリ相当の動作仕様を満たす(→id:yohhoy:20120404)- lock/try_lockメンバ関数における
mtx_
ロック外でのowner_.load(relaxed)
は、atomic変数であるためdata race free。 - このとき自スレッドがロック獲得中であれば、"sequenced before" 関係により自スレッドが書込んだ自スレッドIDを観測してtrue側へ分岐する。それ以外であれば、"sequenced before" 関係により自スレッドunlockで書込んだ値
thread::id()
、または "visible sequence of side effects" により他スレッドが書込んだ値を観測してfalse側へ分岐する。このとき他スレッドID(他スレッドがロック獲得中)と観測できなかったとしても、続くmtx_.lock
操作でブロックされるためrecursive_mutex動作仕様を満たす。 - unlockメンバ関数では
owner_.store(relaxed)
であっても、続くmtx_.unlock
がreleaseセマンティクスを持つため、値thread::id()
代入結果は他スレッドから可視となる。(直接的に上記動作へは寄与しない)
- lock/try_lockメンバ関数における