Цикл, не потребляя слишком много циклов процессора и без сна ()? - PullRequest
7 голосов
/ 10 января 2011

Я делаю программу VoIP, которая постоянно проверяет, есть ли в буфере аудиозаписи что-либо (библиотека FMOD, когда функция getRecordPosition> 0, тогда в буфере есть данные).

Так что это будет что-то вроде:

while (true) {
    if(getRecordPosition>0) {
     process data....
    }
}

Однако это приведет к очень высокой загрузке ЦП.Одной из версий было бы использовать sleep (), но я бы предпочел не использовать его, если это возможно.Например, обработка сообщений win32 с помощью цикла, управляемого событиями, не потребляет много циклов ЦП, и я пытаюсь имитировать это.В то же время я понимаю, что функцию getRecordPosition () нужно будет часто вызывать, чтобы увидеть, будет ли возвращаемое значение больше 0.

Не могу ли я выполнить цикл while (true) и sleep () для некоторыхнебольшое количество времени, чтобы сохранить низкую загрузку процессора?

Я гуглил и сделал какой-то поиск, но большинство возвращает либо с помощью sleep (), либо с некоторой синхронизацией POSIX с мьютексом.(Я работаю с приложением Win32 для C ++)

Cheers

--- EDIT: забыл упомянуть, что у меня нет доступа к исходному тексту fmod: / ---

Ответы [ 6 ]

5 голосов
/ 10 января 2011

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

(следует psudocude)

Основной поток:

HANDLE buf_event = CreateEvent(...);
// ...
CreateThread(BufferControl, ...);

Поток с буферной записью:

OnWriteToBuffer()
{
  buffer.Write(...);
  SetEvent(buf_event);
}

А затем в потоке, в котором вы хотите что-то сделать, когда в буфере ожидают данные, дождитесь, когда событие будет сообщено:1012 * Тема с буферным считыванием

rc = WaitForSingleObject(buf_event, INFINITE);
if( rc == WAIT_OBJECT_0 )
{
  // there's somethign in the buffer
}
1 голос
/ 10 января 2011

Я не знаком с библиотекой FMOD, но обеспечивает ли она обратный вызов уведомлений, когда данные помещаются в буфер? Если нет, вы в значительной степени застряли, используя какую-то форму сна (вы можете поместить этот код в поток и использовать что-то вроде nanosleep, чтобы по-прежнему иметь хорошее время отклика).

1 голос
/ 10 января 2011

Вы можете использовать SwitchToThread, чтобы передать процессор другому потоку и проверить возвращаемое значение. Если это правда, вы уступили, а если нет, то нет других потоков, которые нужно запускать. Если я правильно помню, FMOD запускает поток, так что вы, вероятно, уступите этому потоку.

Если он не дает результата или продолжает использовать много процессорного времени, вы можете использовать некоторую комбинацию уступок и сна.

0 голосов
/ 10 января 2011

Чтобы избежать использования процессора и избежать неэффективности функции Sleep (), вам нужно избегать опроса, вместо этого используйте механизм, управляемый событиями. Для этого есть готовые рамки. Например, в GBL вы должны определить сигнал, скажем, getRecordPosition, и связать его с обработчиком:

Handler([](){ do_something(); }) << getRecordPosition;

или если вам нужен отдельный поток, вы бы подождали сигнала:

CreateThread([](){ Wait(getRecordPosition); do_something(); });
0 голосов
/ 10 января 2011

Рассмотрим другие примитивы синхронизации, которые может предложить Win32.Событие автосброса звучит так, как вам нужно.Они тоже работают перекрестно.

0 голосов
/ 10 января 2011

Мы столкнулись с подобной проблемой.
У нас много процессов, пытающихся поделиться ресурсом.После того, как один из них удерживал этот ресурс, другой должен ждать, пока этот ресурс станет доступным.Это означает, что нужно подождать некоторое время, затем попытаться заблокировать ресурс и, если оно недоступно, снова заснуть.
Поскольку нам приходится разрабатывать этот код как в Windows, так и в Linux, мы столкнулись с различными решениями, даже с использованием boost (но без подтвержденияРезультаты).В любом случае, лучшим решением в Windows было использование WaitForSingleObject () на ресурсе, но в Linux нам приходилось спать всего 1 миллисекунду.Кажется, что это решение потребляет очень низкую загрузку ЦП - вместо некоторого времени (true) - предоставление ресурса, который будет взят как можно скорее.

В начале мы теряли много времени на сон между проверкой доступности ресурсов и следующим, так как мы спим в течение многих миллисекунд.Теперь мы на самом деле очень быстро.НТН

...