Здравствуйте All !
Есть поток (библиотека pthreads). Поток в режиме простоя выполняет
select и ждет PIPE записей.
Вопрос:
Как правильно организовать таймер в потоке который должен завершать SELECT по
неполучению ожидаемых в select данных ? (SetTimer и ClearTimer)
(таймаут указываемый в select - не годится - у него другая функция,
сигналы - не понял можноли их использовать в потоках. Потоков может
быть несколько.).Примерный каркас чего хочется (конечно это только модель):
while (!Terminated) {
select() ;
if (FD_ISSET(NewData)) { SendData() ; SetTimer() ; }
else if (FD_ISSET(AnswToSendData)) { ClearTimer() ; }
else if (FD_ISSET(IsTimer)) {
errmsg("Не получили подтверждения на посланные данные") ;
}
}
----------------------------
С уважением Алексей.
интересно а какая по вашему функция у таймаута в select() :)
>интересно а какая по вашему функция у таймаута в select() :)
Я понимаю вышу улыбку :) но тем не менее данный таймер служит в программе для других вещей - посылки пилот сигнала при отсутствии данных. Данный период значительно больше нужного мне времени.
Вопрос от того, что я еще не очень хорошо ориентируюсь в библиотеках Linux, но знаю что в Windows такие функции выполняет системный вызов. Поэтому не желая "изобретать велосипед" надеюсь что чтото подобное в Linux тоже должно существовать.Если такого нет - вроде как просится отдельный thread "спящий" нужное мне время, а затем делающий запись в нужный pipe - для того чтобы "разбудить" select основного потока.
А может это лучше делать с помощью сигналов SIGALRM ?
Какой путь правильный ?
С уважением Алексей.
>
>А может это лучше делать с помощью сигналов SIGALRM ?
>
>Какой путь правильный ?Правильный путь - не использовать совместно select()/pool() и alarm()
Если для задачи милисекундные таймеры малы,
то скорее всего Вам нужно выбрать другую систему
и почти наверняка это будет ОС реального времени.
>Правильный путь - не использовать совместно select()/pool() и alarm()
>
>Если для задачи милисекундные таймеры малы,
>то скорее всего Вам нужно выбрать другую систему
>и почти наверняка это будет ОС реального времени.Спасибо за ответ.
Буду реализовывать свой CTimer c thread реализацией и PIPE сигнализацией.С уважением Алексей.
из man select:select использует тайм-аут в виде struct timeval (с секундами и микросекундами), тогда как pselect использует struct timespec (с секундами и наносекундами).
Или наносекунд тоже мало? :)
>как pselect использует struct timespec (с секундами и наносекундами).
>Или наносекунд тоже мало? :)
Дело не в иочности select а в том, что этот таймаут уже используется для других целей. Поэтому нужен процесс, который бы будил наш select по условию.
Реализовал в виде класса на основе pthread. Работает.//----------------------------- CTimer --------------------------------------
//
CTimer::CTimer(int _Interval):
Interval(_Interval), SyncPipe(0,O_NONBLOCK) {
}
void CTimer::Enable(bool Yes) {
if (Yes) Resume() ; else Terminate() ;
}
void CTimer::AfterTic() { char C ; TryRead(SyncPipe.RFd(),&C,1,"CTimer::AfterTic") ; }
void *CTimer::Execute() {
while (!Terminated) { fd_set ReadFds ; FD_ZERO(&ReadFds) ;
FD_SET(EndThreadPipe.RFd(),&ReadFds) ;
int MaxFd=EndThreadPipe.RFd() ; MaxFd+=1 ;
timeval TimeOut ; TimeOut.tv_sec=Interval/1000 ; TimeOut.tv_usec=(Interval*1000)%1000 ; // Период пилот сигнала
int Ret=select(MaxFd,&ReadFds,NULL,NULL,&TimeOut) ;
if (Terminated) break ;
if (Ret>0) {
} else if (Ret==0) { // Таймаут
char C ; TryWrite(SyncPipe.WFd(),&C,1,"CTimer::Execute() Таймаут") ;
} else { int Err=errno ;
if (Err!=EINTR) errmsgerrno("CTimer::Execute Ошибка Select") ;
}
}
return NULL ;
}