From a76a338e8e8d746e73df2b78a6f59392017bbc33 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Wed, 26 Jun 1996 22:14:15 +0000 Subject: [PATCH] added new src files --- src/libCom/Makefile.Unix | 10 +- src/libCom/osiTime.h | 231 +++++++++++++++++++++++++ src/libCom/osiTimeOSD.cc | 27 +++ src/libCom/osiTimer.cc | 305 ++++++++++++++++++++++++++++++++++ src/libCom/osiTimer.h | 135 +++++++++++++++ src/libCom/timer/osiTimer.cpp | 305 ++++++++++++++++++++++++++++++++++ src/libCom/timer/osiTimer.h | 135 +++++++++++++++ 7 files changed, 1146 insertions(+), 2 deletions(-) create mode 100644 src/libCom/osiTime.h create mode 100644 src/libCom/osiTimeOSD.cc create mode 100644 src/libCom/osiTimer.cc create mode 100644 src/libCom/osiTimer.h create mode 100644 src/libCom/timer/osiTimer.cpp create mode 100644 src/libCom/timer/osiTimer.h diff --git a/src/libCom/Makefile.Unix b/src/libCom/Makefile.Unix index b8b918666..5b1b1bd33 100644 --- a/src/libCom/Makefile.Unix +++ b/src/libCom/Makefile.Unix @@ -18,6 +18,8 @@ INC += tsDefs.h INC += bucketLib.h INC += pal.h INC += fdMgr.h +INC += osiTime.h +INC += osiTimer.h SRCS.c += ../bucketLib.c SRCS.c += ../calcPerform.c @@ -39,7 +41,9 @@ SRCS.c += ../postfix.c SRCS.c += ../realpath.c SRCS.c += ../tsSubr.c SRCS.c += ../assertUNIX.c -#SRCS.c += ../fdMgr.cc +SRCS.c += ../fdMgr.cc +SRCS.c += ../osiTimer.cc +SRCS.c += ../osiTimeOSD.cc LIBOBJS += bucketLib.o LIBOBJS += calcPerform.o @@ -60,7 +64,9 @@ LIBOBJS += postfix.o LIBOBJS += realpath.o LIBOBJS += tsSubr.o LIBOBJS += assertUNIX.o -#LIBOBJS += fdMgr.o +LIBOBJS += fdMgr.o +LIBOBJS += osiTimer.o +LIBOBJS += osiTimeOSD.o LIBNAME = libCom.a diff --git a/src/libCom/osiTime.h b/src/libCom/osiTime.h new file mode 100644 index 000000000..28b11e2f0 --- /dev/null +++ b/src/libCom/osiTime.h @@ -0,0 +1,231 @@ +/* + * $Id$ + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * + * History + * $Log$ + * Revision 1.2 1996/06/21 02:03:40 jhill + * added stdio.h include + * + * Revision 1.1.1.1 1996/06/20 22:15:56 jhill + * installed ca server templates + * + * + */ + + +#ifndef osiTimehInclude +#define osiTimehInclude + +#include +#include +#ifndef assert // allows use of epicsAssert.h +#include +#endif + +const unsigned nSecPerSec = 1000000000u; +const unsigned nSecPerUSec = 1000u; +const unsigned secPerMin = 60u; + +class osiTime { + static friend osiTime operator+ + (const osiTime &lhs, const osiTime &rhs); + static friend osiTime operator- + (const osiTime &lhs, const osiTime &rhs); + static friend int operator>= + (const osiTime &lhs, const osiTime &rhs); +public: + osiTime () : sec(0u), nSec(0u) {} + osiTime (const osiTime &t) : sec(t.sec), nSec(t.nSec) {} + osiTime (const unsigned long secIn, const unsigned long nSecIn) + { + if (nSecInsec = secIn; + this->nSec = nSecIn; + } + else if (nSecIn<(nSecPerSec<<1u)){ + this->sec = secIn + 1u; + this->nSec = nSecIn-nSecPerSec; + } + else { + this->sec = nSecIn/nSecPerSec + secIn; + this->nSec = nSecIn%nSecPerSec; + } + } + osiTime (double t) + { + double intPart; + if (t<0.0l) { + t = 0.0l; + } + this->sec = (unsigned long) t; + intPart = (double) this->sec; + this->nSec = (unsigned long) ((t-intPart)*nSecPerSec); + } + + // + // fetched as fields so this file is not required + // to include os dependent struct timeval + // + void getTV(long &secOut, long &uSecOut) const + { + assert (this->sec<=LONG_MAX); + secOut = (long) this->sec; + assert (this->nSec<=LONG_MAX); + uSecOut = (long) this->nSec/nSecPerUSec; + } + // + // + void get(long &secOut, long &nSecOut) const + { + assert(this->sec <= LONG_MAX); + secOut = this->sec; + assert(this->nSec <= LONG_MAX); + nSecOut = this->nSec; + } + void get(unsigned long &secOut, unsigned long &nSecOut) const + { + secOut = this->sec; + nSecOut = this->nSec; + } + void get(unsigned &secOut, unsigned &nSecOut) const + { + secOut = this->sec; + nSecOut = this->nSec; + } + + operator double() const + { + return ((double)this->nSec)/nSecPerSec+this->sec; + } + operator float() const + { + return ((float)this->nSec)/nSecPerSec+this->sec; + } + static osiTime getCurrent(); + + osiTime operator+= (const osiTime &rhs); + osiTime operator-= (const osiTime &rhs); + + void show(unsigned) + { + printf("osiTime: sec=%lu nSec=%lu\n", + this->sec, this->nSec); + } +private: + unsigned long sec; + unsigned long nSec; +}; + +inline osiTime operator+ (const osiTime &lhs, const osiTime &rhs) +{ + return osiTime(lhs.sec + rhs.sec, lhs.nSec + rhs.nSec); +} + +inline osiTime osiTime::operator+= (const osiTime &rhs) +{ + *this = *this + rhs; + return *this; +} + +// +// like data type unsigned this assumes that the lhs > rhs +// (otherwise we assume sec wrap around) +// +inline osiTime operator- (const osiTime &lhs, const osiTime &rhs) +{ + unsigned long nSec, sec; + + if (lhs.sec= (const osiTime &lhs, const osiTime &rhs) +{ + int rc; +// +// Sun's CC -O generates bad code here +// +// +// +#if 0 + if (lhs.sec>rhs.sec) { + return 1; + } + else if (lhs.sec==rhs.sec) { + if (lhs.nSec>=rhs.nSec) { + return 1; + } + } + assert(lhs.sec<=rhs.sec); + return 0; +#endif + if (lhs.sec>rhs.sec) { + rc = 1; + } + else if (lhs.sec=rhs.nSec) { + rc = 1; + } + else { + rc = 0; + } + } + return rc; +} + +#endif // osiTimehInclude + diff --git a/src/libCom/osiTimeOSD.cc b/src/libCom/osiTimeOSD.cc new file mode 100644 index 000000000..69b22af99 --- /dev/null +++ b/src/libCom/osiTimeOSD.cc @@ -0,0 +1,27 @@ + +#include + +#include +#include + +#ifdef SUNOS4 +extern "C" { +int gettimeofday (struct timeval *tp, struct timezone *tzp); +} +#endif + +// +// osiTime::getCurrent () +// +osiTime osiTime::getCurrent () +{ + int status; + struct timeval tv; + struct timezone tzp; + + status = gettimeofday (&tv, &tzp); + assert (status==0); + + return osiTime(tv.tv_sec, tv.tv_usec * nSecPerUSec); +} + diff --git a/src/libCom/osiTimer.cc b/src/libCom/osiTimer.cc new file mode 100644 index 000000000..970761626 --- /dev/null +++ b/src/libCom/osiTimer.cc @@ -0,0 +1,305 @@ +/* + * $Id$ + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * + * History + * $Log$ + * Revision 1.1.1.1 1996/06/20 00:28:15 jhill + * ca server installation + * + */ + +// +// NOTES: +// 1) this should use a binary tree to speed up inserts? +// 2) when making this safe for multi threading consider the possibility of +// object delete just after finding an active fdRegI on +// the list but before callBack(). +// +// + +#include +#include + +#include + +osiTimerQueue staticTimerQueue; + +// +// osiTimer::arm() +// +void osiTimer::arm (const osiTime * const pInitialDelay) +{ + tsDLIter iter (staticTimerQueue.pending); + osiTimer *pTmr; + + // + // calculate absolute expiration time + // (dont call base's delay() virtual func + // in the constructor) + // + if (pInitialDelay) { + this->exp = osiTime::getCurrent() + *pInitialDelay; + } + else { + this->exp = osiTime::getCurrent() + this->delay(); + } + +#ifdef DEBUG + double theDelay; + osiTime copy; + if (pInitialDelay) { + theDelay = *pInitialDelay; + } + else { + theDelay = this->delay(); + } + printf ("Arm of \"%s\" with delay %lf at %x\n", + this->name(), theDelay, (unsigned)this); +#endif + + // + // insert into the pending queue + // + // Finds proper time sorted location using + // a linear search. + // **** this should use a binary tree ???? + // + while ( (pTmr = iter()) ) { + if (pTmr->exp >= this->exp) { + break; + } + } + if (pTmr) { + pTmr = pTmr->getPrev (); + staticTimerQueue.pending.insert (*this, pTmr); + } + else { + staticTimerQueue.pending.add (*this); + } + this->state = ositPending; + +# ifdef DEBUG + staticTimerQueue.show(10u); +# endif +} + +// +// osiTimer::~osiTimer() +// +osiTimer::~osiTimer() +{ + switch (this->state) { + case ositPending: + staticTimerQueue.pending.remove(*this); + break; + case ositExpired: + staticTimerQueue.expired.remove(*this); + break; + case ositLimbo: + break; + default: + assert(0); + } + this->state = ositLimbo; +} + +// +// osiTimer::again() +// +osiBool osiTimer::again() +{ + // + // default is to run the timer only once + // + return osiFalse; +} + +// +// osiTimer::destroy() +// +void osiTimer::destroy() +{ + delete this; +} + +// +// osiTimer::delay() +// +const osiTime osiTimer::delay() +{ + // + // default to 1 sec + // + return osiTime (1.0); +} + +void osiTimer::show (unsigned level) +{ + osiTime cur(osiTime::getCurrent()); + double delay; + + printf ("osiTimer at %x for \"%s\" with again = %d\n", + (unsigned) this, this->name(), this->again()); + if (this->exp >= cur) { + delay = this->exp - cur; + } + else { + delay = cur - this->exp; + delay = -delay; + } + if (level>=1u) { + printf ("\tdelay to expire = %f, state = %d\n", + delay, this->state); + } +} + +// +// osiTimerQueue::delayToFirstExpire() +// +osiTime osiTimerQueue::delayToFirstExpire() +{ + osiTimer *pTmr; + osiTime cur(osiTime::getCurrent()); + osiTime delay; + + pTmr = pending.first(); + if (pTmr) { + if (pTmr->exp>=cur) { + delay = pTmr->exp - cur; + } + else { + delay = osiTime(0u,0u); + } + } + else { + // + // no timer in the queue - return a long delay - 30 min + // + delay = osiTime(30u * secPerMin, 0u); + } +#ifdef DEBUG + printf("delay to first item on the queue %lf\n", (double) delay); +#endif + return delay; +} + +// +// osiTimerQueue::process() +// +void osiTimerQueue::process() +{ + tsDLIter iter (this->pending); + osiTimer *pTmr; + osiTimer *pNextTmr; + osiTime cur(osiTime::getCurrent()); + + // no recursion + if (this->inProcess) { + return; + } + this->inProcess = osiTrue; + + pNextTmr = iter(); + while ( (pTmr = pNextTmr) ) { + if (pTmr->exp >= cur) { + break; + } + pNextTmr = iter(); + this->pending.remove(*pTmr); + pTmr->state = ositExpired; + this->expired.add(*pTmr); + } + + // + // prevent problems if they access the + // above list while in an "expire()" call back + // + while ( (pTmr = this->expired.first()) ) { +#ifdef DEBUG + double diff = cur-pTmr->exp; + printf ("expired %x for \"%s\" with error %lf\n", + pTmr, pTmr->name(), diff); +#endif + pTmr->expire(); + // + // verify that the current timer + // wasnt deleted in "expire()" + // + if (pTmr == this->expired.first()) { + this->expired.get(); + pTmr->state = ositLimbo; + if (pTmr->again()) { + pTmr->arm(); + } + else { + pTmr->destroy(); + } + } + } + this->inProcess = osiFalse; +} + +// +// osiTimerQueue::show() +// +void osiTimerQueue::show(unsigned level) +{ + tsDLIter iter (this->pending); + osiTimer *pTmr; + + printf("osiTimerQueue with %d items pending and %d items expired\n", + this->pending.count(), this->expired.count()); + while ( (pTmr = iter()) ) { + pTmr->show(level); + } +} + +// +// osiTimerQueue::~osiTimerQueue() +// +osiTimerQueue::~osiTimerQueue() +{ + osiTimer *pTmr; + + // + // destroy any unexpired timers + // + while ( (pTmr = this->pending.get()) ) { + pTmr->destroy(); + } + + // + // destroy any expired timers + // + while ( (pTmr = this->expired.get()) ) { + pTmr->destroy(); + } +} + + diff --git a/src/libCom/osiTimer.h b/src/libCom/osiTimer.h new file mode 100644 index 000000000..cfdecd4f3 --- /dev/null +++ b/src/libCom/osiTimer.h @@ -0,0 +1,135 @@ +/* + * $Id$ + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * + * History + * $Log$ + * Revision 1.1.1.1 1996/06/20 22:15:55 jhill + * installed ca server templates + * + * + */ + + +#ifndef osiTimerHInclude +#define osiTimerHInclude + +#include +#include + +enum osiBool {osiFalse=0, osiTrue=1}; +enum osiTimerState {ositPending, ositExpired, ositLimbo}; + +// +// osiTimer +// +class osiTimer : public tsDLNode { + friend class osiTimerQueue; +public: + osiTimer (const osiTime &delay) + { + this->arm(&delay); + } + virtual ~osiTimer(); + + // + // called when the timer expires + // + virtual void expire()=0; + + // + // called if + // 1) osiTimer exists and the osiTimerQueue is deleted + // 2) when the timer expies and again() returs false + // + // osiTimer::destroy() does a "delete this" + // + virtual void destroy(); + + // + // osiTimer::again() returns false + // (run the timer once only) + // returning true indicates that the + // timer should be rearmed with delay + // "delay()" when it expires + // + virtual osiBool again(); + + // + // returns the delay prior to expire + // for subsequent iterations (if "again()" + // returns true) + // + // osiTimer::delay() returns 1 sec + // + virtual const osiTime delay(); + + virtual void show (unsigned level); + + // + // for diagnosics + // + virtual const char *name() + { + return "unknown class deriving from osiTimer"; + } +private: + osiTime exp; + osiTimerState state; + + // + // arm() + // place timer in the pending queue + // + void arm (const osiTime * const pInitialDelay=0); +}; + +// +// osiTimerQueue +// +class osiTimerQueue { +friend class osiTimer; +public: + osiTimerQueue() : inProcess(osiFalse) {}; + ~osiTimerQueue(); + osiTime delayToFirstExpire (); + void process (); + void show (unsigned level); +private: + tsDLList pending; + tsDLList expired; + osiBool inProcess; + + void install (osiTimer &tmr, osiTime delay); +}; + +extern osiTimerQueue staticTimerQueue; + + +#endif // osiTimerHInclude + diff --git a/src/libCom/timer/osiTimer.cpp b/src/libCom/timer/osiTimer.cpp new file mode 100644 index 000000000..970761626 --- /dev/null +++ b/src/libCom/timer/osiTimer.cpp @@ -0,0 +1,305 @@ +/* + * $Id$ + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * + * History + * $Log$ + * Revision 1.1.1.1 1996/06/20 00:28:15 jhill + * ca server installation + * + */ + +// +// NOTES: +// 1) this should use a binary tree to speed up inserts? +// 2) when making this safe for multi threading consider the possibility of +// object delete just after finding an active fdRegI on +// the list but before callBack(). +// +// + +#include +#include + +#include + +osiTimerQueue staticTimerQueue; + +// +// osiTimer::arm() +// +void osiTimer::arm (const osiTime * const pInitialDelay) +{ + tsDLIter iter (staticTimerQueue.pending); + osiTimer *pTmr; + + // + // calculate absolute expiration time + // (dont call base's delay() virtual func + // in the constructor) + // + if (pInitialDelay) { + this->exp = osiTime::getCurrent() + *pInitialDelay; + } + else { + this->exp = osiTime::getCurrent() + this->delay(); + } + +#ifdef DEBUG + double theDelay; + osiTime copy; + if (pInitialDelay) { + theDelay = *pInitialDelay; + } + else { + theDelay = this->delay(); + } + printf ("Arm of \"%s\" with delay %lf at %x\n", + this->name(), theDelay, (unsigned)this); +#endif + + // + // insert into the pending queue + // + // Finds proper time sorted location using + // a linear search. + // **** this should use a binary tree ???? + // + while ( (pTmr = iter()) ) { + if (pTmr->exp >= this->exp) { + break; + } + } + if (pTmr) { + pTmr = pTmr->getPrev (); + staticTimerQueue.pending.insert (*this, pTmr); + } + else { + staticTimerQueue.pending.add (*this); + } + this->state = ositPending; + +# ifdef DEBUG + staticTimerQueue.show(10u); +# endif +} + +// +// osiTimer::~osiTimer() +// +osiTimer::~osiTimer() +{ + switch (this->state) { + case ositPending: + staticTimerQueue.pending.remove(*this); + break; + case ositExpired: + staticTimerQueue.expired.remove(*this); + break; + case ositLimbo: + break; + default: + assert(0); + } + this->state = ositLimbo; +} + +// +// osiTimer::again() +// +osiBool osiTimer::again() +{ + // + // default is to run the timer only once + // + return osiFalse; +} + +// +// osiTimer::destroy() +// +void osiTimer::destroy() +{ + delete this; +} + +// +// osiTimer::delay() +// +const osiTime osiTimer::delay() +{ + // + // default to 1 sec + // + return osiTime (1.0); +} + +void osiTimer::show (unsigned level) +{ + osiTime cur(osiTime::getCurrent()); + double delay; + + printf ("osiTimer at %x for \"%s\" with again = %d\n", + (unsigned) this, this->name(), this->again()); + if (this->exp >= cur) { + delay = this->exp - cur; + } + else { + delay = cur - this->exp; + delay = -delay; + } + if (level>=1u) { + printf ("\tdelay to expire = %f, state = %d\n", + delay, this->state); + } +} + +// +// osiTimerQueue::delayToFirstExpire() +// +osiTime osiTimerQueue::delayToFirstExpire() +{ + osiTimer *pTmr; + osiTime cur(osiTime::getCurrent()); + osiTime delay; + + pTmr = pending.first(); + if (pTmr) { + if (pTmr->exp>=cur) { + delay = pTmr->exp - cur; + } + else { + delay = osiTime(0u,0u); + } + } + else { + // + // no timer in the queue - return a long delay - 30 min + // + delay = osiTime(30u * secPerMin, 0u); + } +#ifdef DEBUG + printf("delay to first item on the queue %lf\n", (double) delay); +#endif + return delay; +} + +// +// osiTimerQueue::process() +// +void osiTimerQueue::process() +{ + tsDLIter iter (this->pending); + osiTimer *pTmr; + osiTimer *pNextTmr; + osiTime cur(osiTime::getCurrent()); + + // no recursion + if (this->inProcess) { + return; + } + this->inProcess = osiTrue; + + pNextTmr = iter(); + while ( (pTmr = pNextTmr) ) { + if (pTmr->exp >= cur) { + break; + } + pNextTmr = iter(); + this->pending.remove(*pTmr); + pTmr->state = ositExpired; + this->expired.add(*pTmr); + } + + // + // prevent problems if they access the + // above list while in an "expire()" call back + // + while ( (pTmr = this->expired.first()) ) { +#ifdef DEBUG + double diff = cur-pTmr->exp; + printf ("expired %x for \"%s\" with error %lf\n", + pTmr, pTmr->name(), diff); +#endif + pTmr->expire(); + // + // verify that the current timer + // wasnt deleted in "expire()" + // + if (pTmr == this->expired.first()) { + this->expired.get(); + pTmr->state = ositLimbo; + if (pTmr->again()) { + pTmr->arm(); + } + else { + pTmr->destroy(); + } + } + } + this->inProcess = osiFalse; +} + +// +// osiTimerQueue::show() +// +void osiTimerQueue::show(unsigned level) +{ + tsDLIter iter (this->pending); + osiTimer *pTmr; + + printf("osiTimerQueue with %d items pending and %d items expired\n", + this->pending.count(), this->expired.count()); + while ( (pTmr = iter()) ) { + pTmr->show(level); + } +} + +// +// osiTimerQueue::~osiTimerQueue() +// +osiTimerQueue::~osiTimerQueue() +{ + osiTimer *pTmr; + + // + // destroy any unexpired timers + // + while ( (pTmr = this->pending.get()) ) { + pTmr->destroy(); + } + + // + // destroy any expired timers + // + while ( (pTmr = this->expired.get()) ) { + pTmr->destroy(); + } +} + + diff --git a/src/libCom/timer/osiTimer.h b/src/libCom/timer/osiTimer.h new file mode 100644 index 000000000..cfdecd4f3 --- /dev/null +++ b/src/libCom/timer/osiTimer.h @@ -0,0 +1,135 @@ +/* + * $Id$ + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * + * History + * $Log$ + * Revision 1.1.1.1 1996/06/20 22:15:55 jhill + * installed ca server templates + * + * + */ + + +#ifndef osiTimerHInclude +#define osiTimerHInclude + +#include +#include + +enum osiBool {osiFalse=0, osiTrue=1}; +enum osiTimerState {ositPending, ositExpired, ositLimbo}; + +// +// osiTimer +// +class osiTimer : public tsDLNode { + friend class osiTimerQueue; +public: + osiTimer (const osiTime &delay) + { + this->arm(&delay); + } + virtual ~osiTimer(); + + // + // called when the timer expires + // + virtual void expire()=0; + + // + // called if + // 1) osiTimer exists and the osiTimerQueue is deleted + // 2) when the timer expies and again() returs false + // + // osiTimer::destroy() does a "delete this" + // + virtual void destroy(); + + // + // osiTimer::again() returns false + // (run the timer once only) + // returning true indicates that the + // timer should be rearmed with delay + // "delay()" when it expires + // + virtual osiBool again(); + + // + // returns the delay prior to expire + // for subsequent iterations (if "again()" + // returns true) + // + // osiTimer::delay() returns 1 sec + // + virtual const osiTime delay(); + + virtual void show (unsigned level); + + // + // for diagnosics + // + virtual const char *name() + { + return "unknown class deriving from osiTimer"; + } +private: + osiTime exp; + osiTimerState state; + + // + // arm() + // place timer in the pending queue + // + void arm (const osiTime * const pInitialDelay=0); +}; + +// +// osiTimerQueue +// +class osiTimerQueue { +friend class osiTimer; +public: + osiTimerQueue() : inProcess(osiFalse) {}; + ~osiTimerQueue(); + osiTime delayToFirstExpire (); + void process (); + void show (unsigned level); +private: + tsDLList pending; + tsDLList expired; + osiBool inProcess; + + void install (osiTimer &tmr, osiTime delay); +}; + +extern osiTimerQueue staticTimerQueue; + + +#endif // osiTimerHInclude +