The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
Интервальный таймер в потоке, !*! oaealex, 23-Апр-07, 13:57  [смотреть все]
Здравствуйте 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("Не получили подтверждения на посланные данные") ;
      }
}


----------------------------
С уважением Алексей.

  • Интервальный таймер в потоке, !*! vic, 16:48 , 23-Апр-07 (1)
    • Интервальный таймер в потоке, !*! oaealex, 07:22 , 24-Апр-07 (2)
      >интересно а какая по вашему функция у таймаута в select() :)


      Я понимаю вышу улыбку :) но тем не менее данный таймер служит в программе для других вещей - посылки пилот сигнала при отсутствии данных. Данный период значительно больше нужного мне времени.
      Вопрос от того, что я еще не очень хорошо ориентируюсь в библиотеках Linux, но знаю что в Windows такие функции выполняет системный вызов. Поэтому не желая "изобретать велосипед" надеюсь что чтото подобное в Linux тоже должно существовать.

      Если такого нет - вроде как просится отдельный thread "спящий" нужное мне время, а затем делающий запись в нужный pipe - для того чтобы "разбудить" select основного потока.

      А может это лучше делать с помощью сигналов SIGALRM ?

      Какой путь правильный ?


      С уважением Алексей.

      • Интервальный таймер в потоке, !*! rmf, 08:19 , 24-Апр-07 (3)
        • Интервальный таймер в потоке, !*! oaealex, 08:52 , 24-Апр-07 (4)

          >Правильный путь - не использовать совместно select()/pool() и alarm()
          >
          >Если для задачи милисекундные таймеры малы,
          >то скорее всего Вам нужно выбрать другую систему
          >и почти наверняка это будет ОС реального времени.

          Спасибо за ответ.
          Буду реализовывать свой CTimer c thread реализацией и PIPE сигнализацией.

          С уважением Алексей.

          • Интервальный таймер в потоке, !*! vic, 12:23 , 24-Апр-07 (5)
            • Интервальный таймер в потоке, !*! oaealex, 11:13 , 26-Апр-07 (6)
              >как 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 ;
              }




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру