yohhoyの日記

技術的メモをしていきたい日記

再帰ミューテックスの実装3つ

C++11標準ライブラリを用いた再帰ミューテックスrecursive_mutexクラスの内部実装 3パターン。標準ライブラリが提供するstd::recursive_mutexの再実装。

各実装で利用している同期プリミティブ

  • #1: std::mutexstd::condition_variable
  • #2: 2個のstd::mutex
  • #3: std::atomicstd::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()代入結果は他スレッドから可視となる。(直接的に上記動作へは寄与しない)