00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <sys/socket.h>
00021 #include <stdio.h>
00022 #include <string.h>
00023 #include <unistd.h>
00024 #include <errno.h>
00025
00026 #include "async_reception.h"
00027 #include "hsms_signums.h"
00028 #include "timer.h"
00029
00030
00031 #define BILLION 1000000000L
00032 #define MILLION 1000000L
00033 #define THOUSAND 1000L
00034
00035 using namespace freesecs;
00036
00037 int ms_timer_t::_subscr_count = 0;
00038 struct sigaction ms_timer_t::_old_act = {};
00039
00040 static char ar_data[1] = {0};
00041
00042 void
00043 ms_timer_t::interrupt(int signo, siginfo_t *info, void *context)
00044 {
00045 char data[1] = {0};
00046
00047 ms_timer_t *tmr = (ms_timer_t*)info->si_value.sival_ptr;
00048
00049 ::write(tmr->_timeout_fd[0], data, 1);
00050 }
00051
00052 ms_timer_t::ms_timer_t()
00053 {
00054 struct sigevent sigev;
00055 struct sigaction act;
00056
00057 if(0 == _subscr_count)
00058 {
00059 memset(&act, 0, sizeof(struct sigaction));
00060 act.sa_flags = SA_SIGINFO;
00061 act.sa_sigaction = interrupt;
00062
00063 if((-1 == sigemptyset(&act.sa_mask)) ||
00064 (-1 == sigaction(TIMEOUT_SIGNAL, &act, &_old_act)))
00065 {
00066 throw 1;
00067 }
00068 }
00069 _subscr_count++;
00070
00071 memset(&sigev, 0, sizeof(sigev));
00072 sigev.sigev_notify = SIGEV_SIGNAL;
00073
00074 sigev.sigev_signo = TIMEOUT_SIGNAL;
00075 sigev.sigev_value.sival_ptr = (void*)this;
00076
00077 if(socketpair(PF_UNIX, SOCK_DGRAM, 0, _timeout_fd))
00078 {
00079 throw;
00080 }
00081
00082 _ar = new async_reception_t(_timeout_fd[1], "timeout");
00083 _ar->data_recvd_signal.add_handler(this, &ms_timer_t::ar_handler);
00084
00085 if(timer_create(CLOCK_REALTIME, &sigev, &_id))
00086 {
00087 throw;
00088 }
00089 }
00090
00091 ms_timer_t::~ms_timer_t()
00092 {
00093 _ar->stop_recv();
00094 delete _ar;
00095
00096 timer_delete(_id);
00097
00098
00099 if(0 == (_subscr_count--))
00100 {
00101 sigaction(TIMEOUT_SIGNAL, &_old_act, NULL);
00102 }
00103 }
00104
00105 int ms_timer_t::start(unsigned long timeout_ms)
00106 {
00107 itimerspec value;
00108 memset(&value, 0, sizeof(itimerspec));
00109 value.it_value.tv_sec = long(timeout_ms/THOUSAND);
00110 value.it_value.tv_nsec = long(timeout_ms*MILLION
00111 - value.it_value.tv_sec*BILLION);
00112
00113 _ar->start_recv(ar_data, 1);
00114
00115 return timer_settime(_id, 0, &value, NULL);
00116 }
00117
00118 int ms_timer_t::stop()
00119 {
00120 itimerspec value;
00121 memset(&value, 0, sizeof(itimerspec));
00122
00123 if(0 != timer_gettime(_id, &value))
00124 {
00125 return errno;
00126 }
00127
00128
00129 if(0 == value.it_value.tv_sec && value.it_value.tv_nsec == 0)
00130 {
00131 return EPERM;
00132 }
00133
00134 _ar->stop_recv();
00135
00136 return timer_settime(_id, 0, &value, NULL);
00137 }
00138
00139 int
00140 ms_timer_t::ar_handler(const size_t&)
00141 {
00142 return _cb();
00143 }
00144
00145
00146 #if 0
00147 class dummy_t
00148 {
00149 public:
00150 int callback()
00151 {
00152 printf("dummy callback.\n");fflush(stdout);
00153 return 0;
00154 }
00155 };
00156
00157 int main(int argc, char *argv[])
00158 {
00159 dummy_t dummy;
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 int error, ix = 0;
00171 while (1)
00172 {
00173 printf("cycle %d: ",ix++);fflush(stdout);
00174 ms_timer_t *t1 = new ms_timer_t;
00175 t1->add_handler(&dummy, &dummy_t::callback);
00176 error = t1->start(1000);
00177 printf("%d\n",error);fflush(stdout);
00178 if(error)
00179 {
00180 break;
00181 }
00182 }
00183 }
00184 #endif