Страницы

Поиск по вопросам

понедельник, 19 ноября 2018 г.

Как прервать чтение по таймеру?

Программа на C, ОС — Windows XP, компилятор — MinGW GCC 3.4.5. Нужен аналог alarm() — SIGALRM. Этого в MinGW нет. Вместо alarm() использовал timeSetEvent() из libwinmm.a. Callback отрабатывает, но read() (на самом деле gets() с консоли) не прерывается (по SIGINT (^C) — прерывается). Вызов raise (SIGILL) из Callback не помогает. Похоже, Callback и основная программа — это разные потоки, а raise генерит сигнал в текущем потоке, то есть в потоке Callback.
Как послать сигнал (в реализации MinGW) в другой поток? Заодно, как определить текущий thread (к сожалению, в Windows я не силен)? Каким еще образом можно прервать ожидание ввода? Желательно получить :
read() == -1; errno == EINTR.
Собственно, задача состоит в эмуляции alarm(), то есть вызове подпрограммы через заданное время. Крайне полезный побочный эффект — прерывание системного вызова (особенно ожидающего события), во время работы которого (системного вызова) сработал таймер. Решение для конкретного случая с использованием setjmp() очевидно, хотелось бы обойтись без него (или максимально спрятать его на уровне вызова alarm()).
Уточнение.
@duff, @тимур, благодарю за внимание.
Хочу сделать alarm() для MinGW (Windows) с поведением аналогично SYSV Unix (то есть блокируемый системный вызов (например read() при срабатывании таймера прерывается).
Вообще говоря, при вызове alarm() неизвестно, будет ли блокировка на сокете, на консоли или на паузе (Sleep()). Желательно прерывать ЛЮБОЕ ожидание. К сожалению, я практически не владею WinAPI, поэтому не знаю, как из вызванной по срабатыванию таймера CallBack функции:
определить, находится ли поток (thread) с main() в состоянии ожидания. (ждет какого-либо семафора в ядре?) (предполагаем однопоточную с точки зрения программиста, вызывающего alarm(), схему). прервать ожидание с возвратом из системного вызова (наверное правильно говорить о функции WinAPI ?) с осмысленным результатом.
Если можно поподробнее о том, где почитать о kbhit, ReadFile, CancelIO
Надеюсь правильно понял (особенно ХэшКод).
Благодарю всех за советы по WinAPI, буду изучать и пробовать.
Искренне Ваш, avp


Ответ

Чтобы не блокировать ввод, можно попробовать:
для POSIX - kbhit + select для WinAPI - ReadFile + CancelIO
Еще раз перечитал вопрос. Если просто нужно прервать чтение по таймеру, то select — лучший вариант.
Чтобы реализовать alarm() для MinGW, придется работать с Windows API (я другого способа не вижу). Вам потребуются
CreateThread WaitForSingleObject SetWaitableTimer
Об этих и других функциях, которые понадобятся, а также примерах их использования лучше всего читать прямо в MSDN.

Комментариев нет:

Отправить комментарий