I am writing a zero-latency cloud gaming server. It's a software pipeline. In the first stage we capture the screen and in the second stage we encode it to the video.
However after some amount of time the second stage freezes. I tried many platform-indepandent approach, but in vein, either of them will freeze eventually. The answer of How to prevent threads from starvation in C++11 stated that we should use mutex. I tried it. And it can last longer but it still freeze sometimes(rarely). I think mutex is not a explicit hint to prevent thread starvation too. (maybe I am doing wrong?)
Now I use mutex and disable Windows priority boost feature at the same time, but I don't like this solution at all. could anyone provide an example of starvation-free producer and consumer(better in C++11)?
producer:
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);
}
}
consumer:
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);
}
}
...
Initially I did not do any protection to circular queue. I think there no race condition(one producer and one consumer). Then I try to add mutex but nothing change....