私はゼロレイテンシのクラウドゲームサーバーを作成しています。それはソフトウェアのパイプラインです。最初の段階では画面をキャプチャし、2番目の段階ではビデオにエンコードします。スレッドスターベートを防ぐ方法
しかし第二段階のフリーズ、ある程度の時間後。私は多くのプラットフォームに依存しないアプローチを試みましたが、静脈ではどちらかが最終的にフリーズします。 How to prevent threads from starvation in C++11の答えは、mutexを使うべきだと述べています。私はそれを試してみました。それは長く続くことができますが、時には(まれに)時折凍ることがあります。ミューテックスはスレッドの飢餓を防ぐための明確なヒントではないと私は思う。 (多分私が間違っているの?)
今私はミューテックスを使用すると同時に、Windowsの優先順位のブースト機能を無効にするが、私は全くこのソリューションを好きではありません。誰も飢餓のない生産者と消費者(C++ 11では良い)の例を提供することができますか?
プロデューサー:
while(Streamer.IsConnected()) {
uint8_t *pBits = Streamer.AcquireNext();
// The buffer is full
if(pBits && get_counter(&fps_limiter) >= 1000/args.m_MaxFps && check_target_window(args.m_TargetWindow.c_str(), limit, &rect)) {
BROFILER_FRAME("MainLoop")
start_counter(&fps_limiter);
if(!FAILED(capture_screen(g_DXGIManager, rect, pBits)))
Streamer.PushNext();
}
else {
this_thread::yield();
// lower cpu usage
Sleep(1);
continue;
}
if (get_counter(&bit_rate) >= 1000) {
uint32_t bps = Streamer.GetBitRate();
printf("\rBirate: %u bps, %u Bps\t\t\t\t\t", bps, bps/8);
start_counter(&bit_rate);
}
}
消費者:
while(!m_ServerShouldStop) {
uint8_t *data = AcquireLast();
if (!data) {
this_thread::yield();
Sleep(1);
continue;
}
// encoder callback
uint8_t *out;
uint32_t size = m_Encoder(data, &out);
PopLast();
// If encoder output something, send it immediately
if(size>0) {
// send the size of buffer
int res1 = ::send_whole_buffer(client_sck, reinterpret_cast<uint8_t *>(&size),
sizeof(size));
// then the contents
int res2 = ::send_whole_buffer(client_sck, out, size);
bytes += size;
if (m_EventHandler)
m_EventHandler->onFrameSent();
// If any of them fails....
if(!res1||!res2)
break;
}
if (get_counter(&counter) >= 1000) {
m_Bps = bytes * 8;
bytes = 0;
start_counter(&counter);
}
}
...
は当初、私は循環キューへの保護をしませんでした。競争状態はないと思う(プロデューサーと消費者はそれぞれ1人)。それから私は
私は、スレッドが何をしているのスタックトレースを取ることをお勧めします。スレッドがWaitForSingleObjectのような関数に座っていると、大きな糸口ができます。一列に2つのスタックトレースを入れて確かめてください。 – Steve
私はbrofiler(githubで利用可能)と呼ばれるプロファイラを使用します。 Windows APiIをフックします。私はWaitForSingleObjectを明示的に呼び出さなかった。しかし、それはスレッドがそれに入るようです。 (しかし、それは戻ってくるでしょう) –
うーん、もし本当に*飢えの問題だったら、ブースト機能を削除するのは間違ったことです。あなたはデッドロックの問題を隠している、非常に悪い考え。プロデューサー - コンシューマーロックは、Boostとwinapi(InitializeSRWLockなど)からすぐに入手できます。自分で作成しないでください。 –