私は現在 pthreads を使用しており、スレッドの 1 つに run() メソッドがあります。run() メソッドは、ベクトルの最初の要素の開始時刻をチェックし、その時刻に達するまでブロッキング スリープを実行して、他のスレッドを実行できるようにする必要があります。問題は、ベクトルのフロント要素が更新される可能性があり、run() メソッドでタイマーをリセットする必要があることです。この問題へのアプローチ方法がよくわかりません。以前の時間に更新された可能性がある最後のチェックの開始時間まで待機するため、スリープを使用できません。
2 に答える
pthread_kill() を使用して、sigtimedwait() でスリープしている特定のスレッドを起こすことができます。
sigset_t _fSigMask; // global sigmask
スレッドを作成する前にこれを行います。スレッドは、スレッドを作成したスレッドからシグナル マスクを継承します。SIGUSR1 を使用してスレッドにシグナルを送ります。他の信号も利用できます。
sigemptyset(&_fSigMask);
sigaddset(&_fSigMask, SIGUSR1);
sigaddset(&_fSigMask, SIGSEGV);
次に、スレッドをスリープさせます。
int nSig;
struct timespec tmTimeout = { nSec, nNanoSec }; // from your vector of times
sigtimedwait(&fSigMask, &nSig, &tmTimeout);
次に、スレッド pThread をウェイクアップするには、シグナルを送るだけです。
pthread_kill(pThread, SIGUSR1);
ちなみに、テスト中、この方法でスレッドをスリープおよび起動すると、条件変数を使用するよりも何倍も高速でした。
ベクトルを更新するものは何でも、スリープしているスレッドに何らかの方法で信号を送る必要があります。これを行うには12の方法がありますが、2つの明らかな方法は、条件変数、またはパイプなどでselectを使用することです。
条件変数を使用pthread_cond_timedwait
すると、計算されたタイムアウト値で使用できます。タイムアウトした場合は、問題ありません。信号が届いた場合は、ベクトルを読み取り、タイムアウトを再計算して、再度ブロックする必要があります。
同様select()
に、パイプのタイムアウトまたは入力を待機している間、ベクトルとブロックからタイムアウト値を計算して使用します。ベクトルを更新しているものは何でもパイプに何かを書き込み、スレッドはウェイクアップし、再計算します...