Лучший способ реализовать занятый цикл?
Каков наилучший способ реализации занятого цикла? поправь меня если я не прав?
while (1); // obviously eats CPU.
while (1) { sleep(100); } // Not sure if it is the correct way ?
3 ответа
Чтобы сделать бесконечное ожидание, для сигнала (что еще) есть pause()
системный вызов. Вы должны будете поместить его в цикл, поскольку он возвращает (всегда с -1 и errno установлен в EINTR) каждый раз, когда сигнал доставляется:
while (1)
pause();
Любопытно, что AFAIK - единственная документально подтвержденная функция POSIX, которая всегда дает сбой.
ОБНОВЛЕНИЕ: благодаря dmckee, в комментариях ниже, sigsuspend()
и всегда терпит неудачу. Это так же, как pause()
, но это более благоприятно для сигнала. Разница в том, что у него есть параметры, поэтому он может потерпеть неудачу с EFAULT
в дополнение к EINTR
,
Занятый цикл - это цикл, который никогда не блокирует и постоянно проверяет некоторые условия. Малый сон достаточно хорош, чтобы избежать 100% использования процессора.
Лучший способ реализовать занятое ожидание - не реализовывать его. Вместо этого вы можете использовать блокировку вызовов или обратных вызовов.
В Linux уже давно есть pselect (POSIX 1.g). Если вы используете обработчики сигналов или определяемые пользователем сигналы, я думаю, что это стоит изучить. В нем также рассматриваются некоторые тонкие расовые условия, которые проявляются в других подходах.
Я знаю, что вы упомянули "занятую петлю", но я думаю, что вам нужна "блокирующая петля".
Как предотвратить его оптимизацию за счет зависимостей данных
Во-первых, конечно, вам следует использовать занятые циклы только в том случае, если у вас есть веская причина не использовать незанятые циклы, которые, как правило, более эффективны, см. Https://codereview.stackexchange.com/questions/42506/using-a- для цикла или сна для ожидания коротких интервалов времени
Теперь, сосредоточившись только на занятых циклах, если вы просто напишете что-то вроде:
while (1);
или:
for (unsigned i = 0; i < 100; i++);
тогда оба из них могут быть оптимизированы, как указано в: Разрешено ли компиляторам исключать бесконечные циклы?
По этой причине, как подробно описано в разделе: Как предотвратить оптимизацию GCC цикла ожидания занятости? Я бы написал их как:
while (1) asm("");
или:
for (unsigned i = 0; i < 100; i++) {
__asm__ __volatile__ ("" : "+g" (i) : :);
}