/* * Copyright (c) 1996 Gunther Schadow. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #pragma implementation #include #include /********************************************************************** * Timer **********************************************************************/ Signal Timer::_sigalrm(SIGALRM, alrmsuperhandler, 0, Signal::f_restart | Signal::f_disable); Timer *Timer::_active_timer = NULL; int Timer::alrmsuperhandler(Signal &) { if(_active_timer == NULL) return 0; // not my signal; Timer &that = *_active_timer; that._alrm_cnt++; if(that._handler != NULL) (that._handler)(that); return 1; // we assume that the signal was for us } Timer::Timer(u_int vsec, u_int vusec, u_int isec, u_int iusec, alrmhdl_t hdl) { bool b = _sigalrm.block(); _handler = hdl; _alrm_cnt = 0; _orig_timer = NULL; _val.it_value.tv_sec = vsec; _val.it_value.tv_usec = vusec; _val.it_interval.tv_sec = isec; _val.it_interval.tv_usec = iusec; _init_val = _val.it_value; getitimer(ITIMER_REAL, &_orig_val); _orig_timer = _active_timer; _active_timer = this; setitimer(ITIMER_REAL, &_val, &_orig_val); _sigalrm.block(b); } Timer::~Timer() { bool b = _sigalrm.block(); if(_active_timer == this) _active_timer = _orig_timer; // Calculate the new timer value itimerval now; // the current value getitimer(ITIMER_REAL, &now); Timeval t(_val.it_interval); // the current interval t *= _alrm_cnt; // times the number of timeouts t += _init_val; // plus the value first loaded *(Timeval*)&_val.it_interval -= *(Timeval*)&now.it_value; t += _val.it_interval; // plus time since last timeout // t is the time elapsed since this timer was installed *(Timeval*)&_orig_val.it_value -= t; // update the original value setitimer(ITIMER_REAL, &_orig_val, NULL); _sigalrm.block(b); } void Timer::get(u_int *vsec, u_int *vusec, u_int *isec, u_int *iusec) const { itimerval val; getitimer(ITIMER_REAL, &val); if(vsec != NULL) *vsec = val.it_value.tv_sec; if(vusec != NULL) *vusec = val.it_value.tv_usec; if(isec != NULL) *isec = val.it_interval.tv_sec; if(iusec != NULL) *iusec = val.it_interval.tv_usec; } /********************************************************************** * Timeval **********************************************************************/ const Timeval Timeval::null(0, 0); const Timeval &Timeval::operator -= (const Timeval &x) { long us = tv_usec - x.tv_usec; long s = tv_sec - x.tv_sec; if(us < 0) { long compl = us / 1000001 + 1; tv_sec = s - compl; tv_usec = us +1000000 * compl; } else { tv_sec = s + us / 1000000; tv_usec = us % 1000000; } if(tv_sec < 0) { tv_sec = 0; tv_usec = 0; } return *this; } void Timer::sleep(u_int vsec, u_int vusec) { Timer t1(vsec, vusec); while(!t1.expired()) pause(); } Timeval::Timeval(u_int sec, u_int usec) { tv_sec = sec + usec / 1000000; tv_usec = usec % 1000000; } const Timeval &Timeval::operator += (const Timeval &x) { tv_usec += x.tv_usec; tv_sec += x.tv_sec + tv_usec / 1000000; tv_usec = tv_usec % 1000000; return *this; } const Timeval &Timeval::operator *= (u_int x) { tv_usec *= x; tv_sec *= x; tv_sec = tv_sec + tv_usec / 1000000; tv_usec = tv_usec % 1000000; return *this; }