まず、mutexと条件変数を使用して実装できることはわかっていますが、最も効率的な実装を可能にしたいと考えています。 競合がない場合は、高速パスのセマフォが必要です。 Linuxではfutexで簡単です。例えば、ここで待ってます:Windowsでのセマフォの高速カウント?
if (AtomicDecremenIfPositive(_counter) > 0) return; // Uncontended
AtomicAdd(&_waiters, 1);
do
{
if (syscall(SYS_futex, &_counter, FUTEX_WAIT_PRIVATE, 0, nullptr, nullptr, 0) == -1) // Sleep
{
AtomicAdd(&_waiters, -1);
throw std::runtime_error("Failed to wait for futex");
}
}
while (AtomicDecrementIfPositive(_counter) <= 0);
AtomicAdd(&_waiters, -1);
とポスト:WindowsはちょうどNtWaitForKeyedEvent()を使用するためにまず
AtomicAdd(&_counter, 1);
if (Load(_waiters) > 0 && syscall(SYS_futex, &_counter, FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0) == -1) throw std::runtime_error("Failed to wake futex"); // Wake one
私は思いました。問題は、カーネルに入る前に_counterの値を原子的にチェックしていないため、NtReleaseKeyedEvent()からの復帰を逃す可能性があるため、直接的な代替ではありません。悪い場合は、NtReleaseKeyedEvent()がブロックされます。 最適なソリューションは何ですか?
セマフォは、共有リソースへの同時アクセスの数を制限します。 mutexはアクセスをシリアライズして、同時ユーザーが待機する必要があります。どちらがいいですか? – AJG85
セマフォ。ミューテックスはロックされたスレッドによってロック解除されるはずです。私は他の人が投稿するセマフォを待っているスレッドが必要です。 –
Hmm ..最初の考え:セマフォカウントが整数で表される場合、負の数になるsemaのアトムデクリメントは、呼び出し側が待機する必要があることを示します。 0または負の結果になるsemaのアトミック・インクリメントは、解放する必要がある待機中のスレッドがあることを示します。これは、スレッドのイベントリストを保護するための「スーパーCS」の1つと一緒に、より高速な「カーネルなし」のパスでより良いセマフォを作成するケースがありますか? –