私は C++ boost::thread ライブラリを使用しています。これは、私の場合は pthreads を使用していることを意味します。公式には、ミューテックスはそれをロックしている同じスレッドからロック解除する必要があり、あるスレッドでロックしてから別のスレッドでロック解除できるという効果が必要です。これを実現するには多くの方法があります。1 つの可能性は、この動作を許可する新しいミューテックス クラスを作成することです。
例えば:
class inter_thread_mutex{
bool locked;
boost::mutex mx;
boost::condition_variable cv;
public:
void lock(){
boost::unique_lock<boost::mutex> lck(mx);
while(locked) cv.wait(lck);
locked=true;
}
void unlock(){
{
boost::lock_guard<boost::mutex> lck(mx);
if(!locked) error();
locked=false;
}
cv.notify_one();
}
// bool try_lock(); void error(); etc.
}
あるスレッドが lock() を呼び出し、別のスレッドが unlock() を呼び出した場合、この最初のスレッドが、待機している他のスレッドより先にロックを取得する可能性があるため、上記のコードは FIFO アクセスを保証しないことを指摘しておく必要があります。(考えてみると、boost::thread のドキュメントでは、ミューテックスまたは条件変数のいずれに対しても明示的なスケジューリング保証が行われていないようです)。しかし、今はそれ (およびその他のバグ) を無視しましょう。
私の質問は、もし私がこの道を進むことにした場合、そのようなミューテックスをブースト ロック可能コンセプトのモデルとして使用できるかどうかです。 boost::unique_lock< inter_thread_mutex >
たとえば、 RAII スタイルのアクセスに を使用し、このロックをboost::condition_variable_any.wait()
などに渡すと、何か問題が発生します。
一方では、なぜそうしないのかわかりません。一方、「なぜだかわからない」というのは、通常、何かがうまくいくかどうかを判断するための非常に悪い方法です。
私が尋ねる理由は、RAII ロックや条件変数などのラッパー クラスを作成する必要があることが判明した場合は、同じ効果を達成するための別の方法を見つけたいからです。
編集:私が望む動作の種類は、基本的に次のとおりです。オブジェクトがあり、変更するたびにロックする必要があります。オブジェクトを 1 つのスレッドからロックし、そのオブジェクトに対して何らかの作業を行いたいと考えています。次に、別のワーカー スレッドに作業を完了するように指示している間、オブジェクトをロックしたままにします。そのため、ワーカー スレッドが終了している間に、最初のスレッドが続行して別の処理を行うことができます。ワーカー スレッドが完了すると、mutex のロックが解除されます。
そして、スレッド 1 が作業を開始してからスレッド 2 が作業を完了するまでの間、他の誰もミューテックス ロックを取得できないように、トランジションをスムーズにしたいと考えています。
inter_thread_mutex のようなものは機能するように見え、プログラムは通常のミューテックスであるかのように対話することもできます。だから、それはきれいな解決策のようです。より良い解決策があれば、それも聞いてうれしいです。
もう一度編集: 最初にロックが必要な理由は、複数のマスター スレッドがあり、共有オブジェクトに無効な方法で同時にアクセスするのを防ぐためにロックが存在するためです。そのため、コードはマスター スレッド レベルでループ レベルのロックのない操作の順序付けを既に使用しています。また、元の実装では、ワーカー スレッドはなく、ミューテックスは通常のコーシャ ミューテックスでした。
inter_thread_thingy は、主に応答時間を改善するための最適化として登場しました。多くの場合、操作 A の「最初の部分」が操作 B の「最初の部分」の前に発生することを保証するのに十分でした。馬鹿げた例として、オブジェクト 1 をパンチして目を黒くしたとします。次に、オブジェクト 1 の内部構造を変更して、すべての組織損傷を反映するように指示します。オブジェクト 2 のパンチに移る前に、組織の損傷を待ちたくありません。ただし、同じ操作の一部として組織の損傷を発生させたいと考えています。たとえば、当面の間、組織の損傷を無効な操作にするような方法で、他のスレッドがオブジェクトを再構成することは望ましくありません。(はい、この例は多くの点で不完全です。いいえ、私はゲームに取り組んでいません)
そのため、オブジェクトの所有権をワーカー スレッドに渡して操作を完了することができるモデルに変更を加えましたが、実際には非常にうまく機能します。すべての操作が完了するのを待つ必要がないため、各マスター スレッドはより多くの操作を実行できます。また、マスター スレッド レベルでのイベント シーケンスは依然としてループベースであるため、高度なマスター スレッド操作を簡単に記述できます。これは、操作が完了したという前提に基づくことができるためです (より正確には、重要な "対応する関数呼び出しが返されたときに、シーケンス ロジックが依存する最初の部分" が完了します。
最後に、すべてを機能させるために必要な同期をカプセル化するために、RAII とブースト ロックを使用して inter_thread ミューテックス/セマフォを使用するとよいと思いました。