Как реализовать пример ждать вокруг блокирующего вызова?

StackOverflow https://stackoverflow.com/questions/4232272

Вопрос

Итак, ситуация в этом. У меня есть библиотека C ++, которая делает некоторую связь между интерпретацией, с wait() Функция, которая блокирует и ждет входящего сообщения. Трудность в том, что мне нужно пример Подождите, что вернется со значением состояния, если сообщение не получено в указанном количестве.

Наиболее элегантным решением, вероятно, переписывает библиотеку, чтобы добавить синхронизированное ожидание его API, но ради этого вопроса я предполагаю, что это не осуществимо. (На самом деле это выглядит сложно, поэтому я хочу знать, что есть другой вариант.)

Вот как бы я сделал это с оживленным петлей ожидания, в псевдокоде:

while(message == false && current_time - start_time < timeout)
{
  if (Listener.new_message()) then message = true;
}

Я не хочу, чтобы оживленное ожидание, которое ест процессорные циклы, хотя. И я также не хочу просто добавлять sleep() Вызов в цикле, чтобы избежать нагрузки процессора, как это означает более медленный ответ. Я хочу что-то, что делает это с правильным блоком и прерыванием. Если лучшее решение включает в себя резьбу (что, вероятно), мы уже используем boost::thread, Поэтому я бы предпочел использовать это.

Я публикую этот вопрос, потому что это похоже на ситуацию, которая будет иметь четкую «лучшую практику», поскольку он является довольно распространенным рисунком. Какой правильный способ сделать это?

Редактировать, чтобы добавить: Большая часть моей обеспокоенности вот в том, что это на месте в программе, которая является как важной эффективностью, так и критически важной, чтобы избежать условий расы или утечек памяти. Таким образом, хотя «используйте два потока и таймер», рекомендуется рекомендациями, я все еще оставил, пытаясь выяснить, как фактически реализовать, что в безопасном и правильном пути, и я могу легко увидеть себя, делая ошибки новичков в коде, который я Даже не знаю, что я сделал. Таким образом, какой-то реальный пример код будет очень оценен!

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

Это было полезно?

Решение

Вы могли бы использовать sigaction(2) и alarm(2), которые являются оба POSIX. Вы устанавливаете действие обратного вызова для тайм-аута, используя sigaction, то вы устанавливаете таймер, используя тревогу, а затем сделать свой блокирующий вызов. Блокирующий вызов будет прерван, если он не завершен в выбранной вами тайм-ауте (в считанные секунды; если вам нужно более тонкую гранулярность, вы можете использовать setitimer(2)).

Обратите внимание, что сигналы в C являются несколько волосатыми, и существует довольно обременительное ограничение на то, что вы можете сделать в вашем обработчике сигнала.

Эта страница полезна и довольно кратко:http://www.gnu.org/s/libc/manual/html_node/setting-an-alarm.html.

Другие советы

Что вы хотите, это что-то вроде Выберите (2), в зависимости от ОС вы нацеливаетесь.

Похоже, вам нужен «монитор», способный сигнал наличию ресурса к потоками через общий MUTEX (как правило). В Boost.Thread A. condition_variable. мог сделать работу.

Вы можете посмотреть на Timed Locks.: Ваш метод блокировки может приспособить блокировку перед тем, как начать ждать и отпустить его, как только данные доступны. Затем вы можете попытаться получить блокировку (с тайменами) в вашем методе ожидания.

Инкапсулировать блокирующий вызов в отдельном потоке. Имейте промежуточный буфер сообщений в этом потоке, которая охраняется переменной условия (как сказано ранее). Сделайте вашу основную тему TOMED-ждать в этой переменной условии. Получите промежуточное хранимое сообщение, если условие выполнено.

Таким образом, в основном поместите новый слой, способный к времени ожидания между API и вашим приложением. Шаблон адаптера.

Касательно

Что происходит с этим вторым потоком, если заблокированный звонок никогда не возвращается?

Я верю, что есть ничего Вы можете сделать, чтобы восстановить чисто Без сотрудничества от вызываемой функции (или библиотеки). «Чисто» означает очистку всех ресурсов, принадлежащих этой нити, включая память, другие потоки, замки, файлы, блокировки на файлах, розетки, ресурсы GPU ... ООН-Члючно, вы действительно можете убить беглый поток.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top