マルチプロセッシング同期のためのポータブルで堅牢なソリューションを長い間探していました。これに触れた人は、良い解決策が boost::iterprocess という名前の同期オブジェクトであることを知っています。しかし....プロセスがnamed_mutexをロックし、プロセスが停止した場合(バグやその他だけでなく、プロセスが停止する通常の状況はたくさんあります。)その場合、named_mutexはロックされた状態のままになります。Ion Gaztanaga (www.boost.org/doc/libs/1_55_0/boost/interprocess/detail/robust_emulation.hpp)によって行われたブースト コードで、robust_mutex を作成する試みがありました。
彼は、状態チェックの放棄をどのように解決するかについて良い考えを持っていました。ゲーム内の各プロセスには独自のロック ファイルがあり、実行中はそのファイルをロックしたままにします。その後、Ion のrobust_mutex チェックは、ロック試行が失敗した場合、現在の所有者がロック ファイルを処理し、現在のミューテックス所有者が生きているかどうかを判断できます。デスミューテックスの場合は取得できます。ファイルロックのトリックは、プロセスが停止した場合にファイルロックがOSによってロック解除されるため、良いアイデアであり、これは移植性が高いようです。このソリューションは、ベースの spin_mutex をラップし、現在の所有者のプロセス ID を内部フィールドに保持します。徹底的なテストを行ったところ、2 つの大きな問題が見つかりました。
ファイル ロックの処理と実装方法は、ファイル ロックを使用するだけで高速になるようにミューテックスを遅くします。
有効なロック ゲート変数と所有者プロセス ID を分離すると、異なるプロセスによってミューテックスが盗まれる状況が発生します。
そして、ここに私の質問があります: 私は両方の問題の解決策を提案しています。
既存のプロセスごとに個別のロック ファイルを使用するのではなく、すべての最終的なプロセス ID (十分な 4MB があるはずです) に対して 1 つのファイルを使用し、各プロセス ロックに対して 1 バイトのみを使用します。そのバイトの位置は、プロセス ID 自体によって決定されます。(これは私の考えではありませんが、Howard Chu と彼の優れた LMDBのコードで見つけました)
spin_mutex をそのままラップするのではなく、コードを書き直して、0/1 の代わりに現在の所有者のプロセス ID をロック ゲートとして使用するようにします。これにより、ロックとロック解除を 1 つのアトミック CAS 操作で行うことができます。
私はそれを実装しようとし、Windowsでテストしました。オリジナルのブースト コードを使用し、必要に応じてブーストを呼び出します。ここにコードがあります。これはプロジェクト ツリーから取得したものなので、テストしたい場合は、一部のインクルードを調整する必要があります。これは提案なので、コード スタイルなどについて私を責めないでください。アイデアやモードが良ければ、どんどん完成させていきます。そうでない場合は、何か他のものを使用しますが、他に何も見つかりません。
recursive_mutex と named_mutex のバージョンもあります。次に、ある種の修正提案があります。これは、あるプロセスが以前に放棄されたミューテックスの所有権を取得した場合、何らかの整合性チェックを行う必要がある可能性が高いからです。
最終的な改善について話し合いたい
前もって感謝します
ラディスラフ。