ブースト ロック可能の概念 (つまり、lock(); unlock(); try_lock();
など) をモデル化するインターフェイスを使用して C++ セマフォ クラスを作成するとします。そのようなオブジェクトへの RAII アクセスにブースト ロックを使用することは安全ですか、または推奨されますか? 言い換えれば、ブースト ロック (および/またはブースト スレッド ライブラリの他の関連部分) は、Lockable の概念が、同じスレッドからロックおよびロック解除されるミューテックスのようなオブジェクトによってのみモデル化されると想定していますか?
私の推測では、Lockable のモデルとしてセマフォを使用しても問題ないはずです。いくつかのブースト ソースを閲覧しましたが、問題ないようです。ロックは、this_thread などへの明示的な参照を格納していないようです。さらに、Lockable の概念には のような機能はありませんwhichThreadOwnsMe()
。boost::unique_lock<MySemaphore>
また、への参照を渡すことさえできるはずboost::condition_variable_any::wait
です。ただし、ドキュメントは要件について明確に明確ではありません。
私が何を意味するかを説明するために、次の行に沿ってベアボーン バイナリ セマフォ クラスを考えてみましょう。
class MySemaphore{
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.
}
ここで、オブジェクトまたはグローバルのどこかに、私が持っているとします。
MySemaphore sem;
RAII を使用してロックおよびロック解除したい。また、あるスレッドから別のスレッドにロックの所有権を「渡す」ことができるようにしたいと考えています。たとえば、私が実行する1つのスレッドで
void doTask()
{
boost::unique_lock<MySemaphore> lock(sem);
doSomeWorkWithSharedObject();
signalToSecondThread();
waitForSignalAck();
lock.release();
}
別のスレッドが次のようなものを実行している間
{
waitForSignalFromFirstThread();
ackSignal();
boost::unique_lock<MySemaphore>(sem,boost::adopt_lock_t());
doMoreWorkWithSameSharedObject();
}
私がこれを行っている理由は、最初のスレッドが実行されてから 2 番目のスレッドが実行さsem
れるまでの間、他の誰かがロックを取得できないようにするためです。基本的に、1 つのタスクを 2 つの部分に分割しています。タスクを分割する理由は、(1) タスクの最初の部分をできるだけ早く開始したい、(2) doTask() が戻る前に最初の部分が完了していることを保証したい、 (3) タスクの 2 番目の、より時間のかかる部分を、マスター スレッドによって開始されたタスクの完了を待機しているスレーブ スレッドのプールから選択された別のスレッドによって完了させたい。doSomeWorkWithSharedObject()
doMoreWorkWithSameSharedObject()
注: 最近、同じ質問 (一種) をここに投稿しましたModeling boost::Lockable with semaphore rather than mutex (以前のタイトル: Unlocking a mutex from a different thread) が、mutex とセマフォを混同したため、ブースト ロックの使用に関する質問本当に対処されませんでした。