summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorchatty1993-04-07 11:56:59 +0000
committerchatty1993-04-07 11:56:59 +0000
commit15b7cecb6b5415a0b2e15a0f4079be05c436e80e (patch)
treefe91a03f113a8a87886fcaa8b9b43b100c4b2885 /utils
parent74139ad518678b6ba69b69b702514c92bf74593e (diff)
downloadivy-league-15b7cecb6b5415a0b2e15a0f4079be05c436e80e.zip
ivy-league-15b7cecb6b5415a0b2e15a0f4079be05c436e80e.tar.gz
ivy-league-15b7cecb6b5415a0b2e15a0f4079be05c436e80e.tar.bz2
ivy-league-15b7cecb6b5415a0b2e15a0f4079be05c436e80e.tar.xz
Reshaped to allow the derivation of timers associated to other sources:
Creation of CCuCoreTimer, base class to CcuBaseTimer
Diffstat (limited to 'utils')
-rw-r--r--utils/Timer.cc309
-rw-r--r--utils/Timer.h68
2 files changed, 217 insertions, 160 deletions
diff --git a/utils/Timer.cc b/utils/Timer.cc
index 7911f9a..a8c4a65 100644
--- a/utils/Timer.cc
+++ b/utils/Timer.cc
@@ -3,7 +3,7 @@
*
* by Stephane Chatty
*
- * Copyright 1992
+ * Copyright 1992-1993
* Centre d'Etudes de la Navigation Aerienne (CENA)
*
* timers
@@ -59,95 +59,28 @@ and if we make sure that a timer is flagged as inactive when we insert it, all w
occurences before the right one will be removed.
!*/
-CcuSignalHandler* CcuBaseTimer::TimeOutHandler = 0;
-CcuBaseTimer* CcuBaseTimer::FirstActive = 0;
-#ifndef CPLUS_BUG19
-CcuListOf <CcuBaseTimer>* CcuBaseTimer::OtherActive = 0;
-#else
-CcuList* CcuBaseTimer::OtherActive = 0;
-#endif
-
-/*?nodoc?*/
-void
-CcuBaseTimer :: ClassInit ()
-{
- TimeOutHandler = new CcuSignalHandler (SigAlrm, &CcuBaseTimer::HandleSignal);
-#ifndef CPLUS_BUG19
- OtherActive = new CcuListOf <CcuBaseTimer>;
-#else
- OtherActive = new CcuList;
-#endif
-}
-
-/*?hidden?*/
-void
-CcuBaseTimer :: StopAlarm ()
-{
- struct itimerval itval;
- timerclear (&itval.it_value);
- timerclear (&itval.it_interval);
- setitimer (ITIMER_REAL, &itval, 0);
-}
-
-/*?hidden?*/
-void
-CcuBaseTimer :: SetAlarm (Millisecond delay)
-{
- if (delay <= 0) {
- StopAlarm ();
- kill (getpid (), SigAlrm);
- return;
- }
-
- struct itimerval itval;
- timerclear (&itval.it_interval);
- itval.it_value.tv_sec = delay / 1000;
- itval.it_value.tv_usec = 1000 * (delay % 1000);
- setitimer (ITIMER_REAL, &itval, 0);
-}
/*!
Remove and return the first active timer in the active timer list.
Timers in that list can actually be inactive.
!*/
/*?hidden?*/
-CcuBaseTimer*
-CcuBaseTimer :: ExtractNextActive ()
+CcuCoreTimer*
+CcuTimerSet :: ExtractNextActive ()
{
- CcuBaseTimer* t;
+ CcuCoreTimer* t;
- /* all entries of OtherActive are valid pointers,
- hence t == 0 iff OtherActive is empty */
+ /* all entries of OtherTimers are valid pointers,
+ hence t == 0 iff OtherTimers is empty */
#ifndef CPLUS_BUG19
- while ((t = OtherActive->RemoveFirst ()) && (t->Status != Active))
+ while ((t = OtherTimers.RemoveFirst ()) && (t->StatusFlag != CcuCoreTimer::Active))
#else
- while ((t = (CcuBaseTimer*) OtherActive->RemoveFirst ()) && (t->Status != Active))
+ while ((t = (CcuCoreTimer*) OtherTimers.RemoveFirst ()) && (t->StatusFlag != CcuCoreTimer::Active))
#endif
;
return t;
}
-#ifndef CPLUS_BUG19
-
-/*?hidden?*/
-int
-CcuBaseTimer :: IsInactive (CcuBaseTimer* t)
-{
- return (t->Status != Active);
-}
-
-#else
-
-/*?hidden?*/
-int
-CcuBaseTimer :: IsInactive (CcuListItem* t)
-{
- return (((CcuBaseTimer*) t)->Status != Active);
-}
-
-#endif /* CPLUS_BUG19 */
-
-
/*!
This function is called by the signal handler. The first active timer is expired
and scheduled again. Then all the timers whose expiration time is earlier
@@ -159,17 +92,24 @@ active timer.
!*/
/*?hidden?*/
void
-CcuBaseTimer :: HandleSignal (int)
+CcuCoreTimer :: Fire (CcuTimerSet* s)
{
+ CcuCoreTimer*& first = s->FirstTimer;
+
+ /* If the first timer is not mature yet, ignore this call */
+ if (!first)
+ return;
CcuTimeStamp now;
+ if (first->NextDate > now)
+ return;
/* Handle the first timer */
- FirstActive->Reschedule ();
- FirstActive->Handle (now);
+ first->Reschedule ();
+ first->Handle (now);
/* handle all other expired timers. */
- CcuBaseTimer* t;
- while (t = ExtractNextActive ()) {
+ CcuCoreTimer* t;
+ while (t = s->ExtractNextActive ()) {
/* Problem : if one Handle () is long, "now" will then be wrong. */
if (t->NextDate > now)
break;
@@ -177,14 +117,33 @@ CcuBaseTimer :: HandleSignal (int)
t->Handle (now);
}
- CcuTimeStamp then;
if (t)
- SetAlarm (t->NextDate - then);
+ t->SetAlarm (t->NextDate);
+
+ first = t;
+}
+
+
+#ifndef CPLUS_BUG19
+
+/*?hidden?*/
+int
+CcuCoreTimer :: IsInactive (CcuCoreTimer* t)
+{
+ return (t->StatusFlag != Active);
+}
+#else
- FirstActive = t;
+/*?hidden?*/
+int
+CcuCoreTimer :: IsInactive (CcuListItem* t)
+{
+ return (((CcuCoreTimer*) t)->StatusFlag != Active);
}
+#endif /* CPLUS_BUG19 */
+
/*?
Create a timer that will send a signal every \var{period} milliseconds, \var{pulses} times.
@@ -192,29 +151,22 @@ If \var{pulses} is negative, the timer will send signals forever.
Timers are activated at creation time. They are disactivated, but not destroyed, after
their last signal.
?*/
-CcuBaseTimer :: CcuBaseTimer (Millisecond period, int pulses)
-: Status (Active),
+CcuCoreTimer :: CcuCoreTimer (Millisecond period, int pulses, CcuTimerSet* set)
+: MySet (set),
+ StatusFlag (Active),
Period (period),
PulsesLeft (pulses)
{
- CcuSignalBlocker b (SigAlrm);
-
- if (!TimeOutHandler)
- ClassInit ();
- if (PulsesLeft != 0)
- Activate ();
}
/*?hidden?*/
-CcuBaseTimer :: ~CcuBaseTimer ()
+CcuCoreTimer :: ~CcuCoreTimer ()
{
- /* stop it */
- if (Status == Active)
- Stop ();
-
+ /* the timer has to be stopped in the derived class */
/* Remove all entries pointing to inactive timers, including this one */
- OtherActive->Remove (IsInactive, CcuList::All);
+ if (MySet)
+ MySet->OtherTimers.Remove (IsInactive, CcuList::All);
}
/*?
@@ -222,7 +174,7 @@ Change the period of a timer. The new period will not be taken into account
before the next time-out.
?*/
void
-CcuBaseTimer :: ChangePeriod (Millisecond period)
+CcuCoreTimer :: ChangePeriod (Millisecond period)
{
CcuSignalBlocker b (SigAlrm);
Period = period;
@@ -233,14 +185,14 @@ Stop this timer if it was running, then start it with its current period.
This function can be used to reset a timer to the beginning of a period.
?*/
void
-CcuBaseTimer :: Restart ()
+CcuCoreTimer :: Restart ()
{
if (PulsesLeft == 0)
return;
/* this function could be optimized: sometimes SetAlarm is called twice. */
CcuSignalBlocker b (SigAlrm);
- if (Status == Active)
+ if (StatusFlag == Active)
Stop ();
Activate ();
}
@@ -252,26 +204,28 @@ first one, the alarm is updated.
!*/
/*?hidden?*/
void
-CcuBaseTimer :: Activate ()
+CcuCoreTimer :: Activate ()
{
+ if (!MySet)
+ return;
CcuTimeStamp now;
NextDate = now + Period;
-
- if (!FirstActive) {
- FirstActive = this;
- SetAlarm (Period);
- } else if (NextDate < FirstActive->NextDate ) {
- SetAlarm (Period);
- OtherActive->Prepend (FirstActive);
- FirstActive = this;
+ CcuCoreTimer*& first = MySet->FirstTimer;
+ if (!first) {
+ first = this;
+ SetAlarm (NextDate);
+ } else if (NextDate < first->NextDate ) {
+ SetAlarm (NextDate);
+ MySet->OtherTimers.Prepend (first);
+ first = this;
} else
Schedule (NextDate);
- Status = Active;
+ StatusFlag = Active;
}
/*?hidden?*/
void
-CcuBaseTimer :: Reschedule ()
+CcuCoreTimer :: Reschedule ()
{
if (PulsesLeft == 0) // this should not happen...
return;
@@ -285,39 +239,40 @@ CcuBaseTimer :: Reschedule ()
/*?hidden?*/
void
-CcuBaseTimer :: Schedule (Millisecond when)
+CcuCoreTimer :: Schedule (Millisecond when)
{
NextDate = when;
/* temporarily set status to inactive so that obsolete entries
- in OtherActive pointing to this timer can be removed */
- Status = Inactive;
+ in OtherTimers pointing to this timer can be removed */
+ StatusFlag = Inactive;
+ CcuListOf <CcuCoreTimer>& others = MySet->OtherTimers;
#ifndef CPLUS_BUG19
- CcuListIterOf <CcuBaseTimer> li (*OtherActive);
- CcuListIterOf <CcuBaseTimer> lj (*OtherActive);
+ CcuListIterOf <CcuCoreTimer> li (others);
+ CcuListIterOf <CcuCoreTimer> lj (others);
#else
- CcuListIter li (*OtherActive);
- CcuListIter lj (*OtherActive);
+ CcuListIter li (others);
+ CcuListIter lj (others);
#endif
while (++li) {
/* while we're at it, remove inactive timers from the list */
#ifndef CPLUS_BUG19
- CcuBaseTimer* cur = *li;
+ CcuCoreTimer* cur = *li;
#else
- CcuBaseTimer* cur = (CcuBaseTimer*) *li;
+ CcuCoreTimer* cur = (CcuCoreTimer*) *li;
#endif
- if (cur->Status != Active) {
- OtherActive->RemoveAfter (lj);
+ if (cur->StatusFlag != Active) {
+ others.RemoveAfter (lj);
li = lj;
} else if (cur->NextDate < NextDate)
++lj;
else
break;
}
- OtherActive->InsertAfter (lj, this);
- Status = Active;
+ others.InsertAfter (lj, this);
+ StatusFlag = Active;
}
/*?
@@ -325,24 +280,23 @@ Stop a timer.
This timer will not deliver any signal until \fun{Restart} is called.
?*/
void
-CcuBaseTimer :: Stop ()
+CcuCoreTimer :: Stop ()
{
- if (Status != Active)
+ if (StatusFlag != Active)
return;
CcuSignalBlocker b (SigAlrm);
-
- Status = Inactive;
+ CcuCoreTimer*& first = MySet->FirstTimer;
+
+ StatusFlag = Inactive;
/* if this timer was the first active one, find another one to replace it */
- if (this == FirstActive) {
- FirstActive = ExtractNextActive ();
- if (FirstActive == 0)
+ if (this == first) {
+ first = MySet->ExtractNextActive ();
+ if (first == 0)
StopAlarm ();
- else {
- CcuTimeStamp now;
- SetAlarm (FirstActive->NextDate -now);
- }
+ else
+ first->SetAlarm (first->NextDate);
}
}
@@ -350,26 +304,103 @@ CcuBaseTimer :: Stop ()
Wait for this timer to expire. If it is stopped, return immediately.
?*/
void
-CcuBaseTimer :: Wait ()
+CcuCoreTimer :: Wait ()
{
- if (Status != Active)
+ if (StatusFlag != Active)
return;
Millisecond next_date = NextDate;
for (;;) {
if (wait (0) >= 0) // not an interrupt
continue;
- if (Status != Active || next_date != NextDate)
+ if (StatusFlag != Active || next_date != NextDate)
return;
}
}
/*?hidden?*/
void
-CcuBaseTimer :: Handle (Millisecond)
+CcuCoreTimer :: Handle (Millisecond)
+{
+}
+
+CcuSignalHandler* CcuBaseTimer::TimeOutHandler = 0;
+CcuTimerSet* CcuBaseTimer::TimerSet = 0;
+
+/*?nodoc?*/
+void
+CcuBaseTimer :: ClassInit ()
+{
+ TimeOutHandler = new CcuSignalHandler (SigAlrm, &CcuBaseTimer::HandleSignal);
+ TimerSet = new CcuTimerSet;
+}
+
+CcuBaseTimer :: CcuBaseTimer (Millisecond period, int pulses)
+: CcuCoreTimer (period, pulses, (TimerSet ? TimerSet : (ClassInit (), TimerSet)))
+{
+ CcuSignalBlocker b (SigAlrm);
+
+ if (PulsesLeft != 0)
+ Activate ();
+}
+
+/*?hidden?*/
+CcuBaseTimer :: ~CcuBaseTimer ()
{
+ /* stop it */
+ if (StatusFlag == Active)
+ Stop ();
}
+/*?hidden?*/
+void
+CcuBaseTimer :: StopAlarm ()
+{
+ struct itimerval itval;
+ timerclear (&itval.it_value);
+ timerclear (&itval.it_interval);
+ setitimer (ITIMER_REAL, &itval, 0);
+}
+
+/*?hidden?*/
+void
+CcuBaseTimer :: SetAlarm (Millisecond when)
+{
+ CcuTimeStamp now;
+ Millisecond delay = when - now;
+
+ if (delay <= 0) {
+ StopAlarm ();
+ kill (getpid (), SigAlrm);
+ return;
+ }
+
+ struct itimerval itval;
+ timerclear (&itval.it_interval);
+ itval.it_value.tv_sec = delay / 1000;
+ itval.it_value.tv_usec = 1000 * (delay % 1000);
+ setitimer (ITIMER_REAL, &itval, 0);
+}
+
+
+/*!
+This function is called by the signal handler. The first active timer is expired
+and scheduled again. Then all the timers whose expiration time is earlier
+that the current time are removed from the list, expired and scheduled again.
+The first non-expired timer, if any, is removed from the list and saved
+as the first active timer.
+Finally, the alarm is set up to expire at the expiration time of the new first
+active timer.
+!*/
+/*?hidden?*/
+void
+CcuBaseTimer :: HandleSignal (int)
+{
+ Fire (TimerSet);
+}
+
+
+
/*?class CcuTimer
The class \typ{CcuTimer} is a derived class of \typ{CcuBaseTimer} that
can be used without deriving a new class.
diff --git a/utils/Timer.h b/utils/Timer.h
index d361802..77c1b70 100644
--- a/utils/Timer.h
+++ b/utils/Timer.h
@@ -3,7 +3,7 @@
*
* by Stephane Chatty
*
- * Copyright 1992
+ * Copyright 1992-1993
* Centre d'Etudes de la Navigation Aerienne (CENA)
*
* timers
@@ -25,48 +25,74 @@ template <class ITEM> class CcuListOf;
#include "List.h"
#endif
-class CcuBaseTimer {
-public:
- enum timer_status { Active, Inactive };
+class CcuCoreTimer;
+
+class CcuTimerSet {
+friend class CcuCoreTimer;
private:
-static CcuSignalHandler* TimeOutHandler;
-static CcuBaseTimer* FirstActive;
+ CcuCoreTimer* FirstTimer;
#ifndef CPLUS_BUG19
-static CcuListOf <CcuBaseTimer>* OtherActive;
+ CcuListOf <CcuCoreTimer> OtherTimers;
#else
-static CcuList* OtherActive;
+ CcuList OtherTimers;
#endif
+ CcuCoreTimer* ExtractNextActive ();
+public:
+inline CcuTimerSet () : FirstTimer (0), OtherTimers () {}
+inline ~CcuTimerSet () {}
+};
-static void ClassInit ();
-static void HandleSignal (int);
-static void SetAlarm (Millisecond);
-static void StopAlarm ();
-static CcuBaseTimer* ExtractNextActive ();
-static int IsInactive (CcuBaseTimer*);
+
+class CcuCoreTimer {
+friend class CcuTimerSet;
+public:
+ enum timer_status { Active, Inactive };
+
+protected:
+static int IsInactive (CcuCoreTimer*);
+
+ CcuTimerSet* MySet;
Millisecond NextDate;
Millisecond Period;
int PulsesLeft;
- timer_status Status;
+ timer_status StatusFlag;
+ CcuCoreTimer (Millisecond, int, CcuTimerSet*);
+ ~CcuCoreTimer ();
void Activate ();
void Schedule (Millisecond);
void Reschedule ();
-
-protected:
+virtual void SetAlarm (Millisecond) = 0;
+virtual void StopAlarm () = 0;
virtual void Handle (Millisecond);
-public:
- CcuBaseTimer (Millisecond, int = -1);
-virtual ~CcuBaseTimer ();
+public:
void ChangePeriod (Millisecond first);
void Stop ();
void Restart ();
void Wait ();
inline Millisecond GetPeriod () const { return Period; }
inline int GetNbPulses () const { return PulsesLeft; }
-inline timer_status GetStatus () const { return Status; }
+inline timer_status GetStatus () const { return StatusFlag; }
+static void Fire (CcuTimerSet*);
+};
+
+class CcuBaseTimer : public CcuCoreTimer {
+private:
+static CcuSignalHandler* TimeOutHandler;
+static CcuTimerSet* TimerSet;
+static void HandleSignal (int);
+static void ClassInit ();
+
+protected:
+ void SetAlarm (Millisecond);
+ void StopAlarm ();
+
+public:
+ CcuBaseTimer (Millisecond, int = -1);
+ ~CcuBaseTimer ();
};
class CcuTimer : public CcuBaseTimer {