Win7 x64 でこの関数と同じ機能を実装する必要があります。
最初に使用SwitchToThread()
しましたが、極端な条件下でデッドロックが発生するため、これは機能しません。私が見つけることができる唯一の代替手段はSleep()
、ミリ秒の解像度でしか機能しないため、これはパフォーマンスキラーである可能性が高く、LockSupport.parkNanos()
.
ナノ秒間隔でスレッドをスケジュールする Java の機能 (それが起こった場合) が疑わしいことがわかったので、スレッドが実行すると想定できるものを実装しました... スピン。ただし、これで問題が解決するかどうかはわかりません.Java関数が機能するにはJVMの介入が必要なように見えるため、避けられないことを遅らせているだけかもしれません。のソース コードはありませんparkNanos
。ネイティブの Sun ライブラリに実装されています。
class LockSupport
{
public:
static void ParkNanos(unsigned __int64 aNanos)
{
ULONGLONG start;
ULONGLONG end;
::QueryUnbiasedInterruptTime(&start);
do
{
// My issue with this is that nothing is actually 'Parked'.
::SwitchToThread();
::QueryUnbiasedInterruptTime(&end);
}
while ((end - start) < aNanos);
}
};
呼び出しコードは次のようになります。
void SomeClass::SomeFunction()
{
while (someCond)
{
LockSupport.parkNanos(1L);
}
}
FWIW、LMAX の Disruptor パターンを C++ に移植しています。デッドロックは、あるスレッドが入っていSingleThreadedClaimStrategy::WaitForFreeSlotAt()
て別のスレッドが入っているときに発生していますBlockingWaitStrategy::WaitFor
(タイムアウトなし)。RingBuffer のサイズが 1、2、4、8 などのように小さい場合、デッドロックはより明白になります。
スレッドは通常のCreateThread
方法で作成されます。
編集:これを書いたときはかなり遅かったので、ここにもう少し情報があります。RingBuffer は__int64
s を保持します。1 つのプロデューサー スレッドと 1 つのコンシューマー スレッドがあります。Consumer スレッドは、Consumer が最後に消費したイベントのシーケンス番号を毎秒ポーリングする Timer スレッドも生成します。コンシューマーが進歩せず、プロデューサーも完了していない時点が来ます。Producer は、カウンタを公開するループを数億回実行するだけです。したがって、私の出力は次のようになります。
898
97
131
Timer: no progress
Timer: no progress
...
すべてが速度のために最適化されているリリース モードでのみ、実際に再現可能です。