Как предотвратить нить голодной

Я пишу облачный игровой сервер с нулевой задержкой. Это программный конвейер. На первом этапе мы делаем снимок экрана, а на втором этапе мы кодируем его в видео.

Однако через некоторое время второй этап замерзает. Я перепробовал многие независимые от платформы подходы, но в любом случае любой из них со временем зависнет. Ответ Как предотвратить голодание потоков в C ++ 11 заявил, что мы должны использовать мьютекс. Я попробовал это. И это может длиться дольше, но все еще иногда замерзает (редко). Я думаю, что мьютекс не является явным намеком на предотвращение истощения потоков. (может я не так делаю?)

Сейчас я использую мьютекс и одновременно отключаю функцию повышения приоритета 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);
}

}
...

Изначально я не делал никакой защиты для кольцевой очереди. Я думаю, что нет условий гонки (один производитель и один потребитель). Затем я пытаюсь добавить мьютекс, но ничего не меняется ….

0

Решение

Слово «Замораживание» подразумевает состояние гонки, а не голодную нить.

Истощение потока — это когда все соответствующие потоки конкурируют за один мьютекс, а один поток (или несколько потоков) продолжает захватить мьютекс, оставляя другие потоки голодными. Это пример плохого дизайна приложения, если у вас так много конкурентов на один Mutex.

Однако вы сказали, что заморозить. Таким образом, замораживание подразумевает, что вы оказались в состоянии Race, когда ни один из (двух или более) потоков не может получить мьютекс или какое-либо другое ограничение в вашем коде.

В вашем вопросе недостаточно информации, чтобы дать какой-либо достойный ответ. Пожалуйста, предоставьте пример кода того, что вы делаете и что именно происходит.

2

Другие решения

Я обнаружил, что моя локальная переменная повреждена функцией моего коллеги. Заставить libx264 работать некорректно. На самом деле код может быть написан без блокировки. Стиль, добавление мьютекса лучше, чем ожидание. может значительно снизить использование процессора

0

По вопросам рекламы [email protected]