/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "xstd/xstd.h"
#include "xstd/Assert.h"
#include "xstd/AlarmClock.h"
#include "xstd/gadgets.h"
AlarmClock TheAlarmClock;
/* Alarm */
void Alarm::ring() {
Assert(theSleeper);
theSleeper->wakeUp(*this);
clear();
}
void Alarm::snooze() {
Assert(theSleeper);
theSleeper->snooze(*this);
clear();
}
void Alarm::set(Time aTime, AlarmUser *aSleeper) {
Assert(aSleeper);
theSleeper = aSleeper;
theTime = aTime;
}
/* AlarmUser */
AlarmUser::AlarmUser(): thePendAlarmCnt(0) {
}
AlarmUser::~AlarmUser() {
cancelAlarms();
}
void AlarmUser::wakeUp(const Alarm &) {
thePendAlarmCnt--;
Assert(thePendAlarmCnt >= 0);
}
// ignore this alarm
void AlarmUser::snooze(const Alarm &) {
thePendAlarmCnt--;
Assert(thePendAlarmCnt >= 0);
}
void AlarmUser::sleepTill(Time time) {
TheAlarmClock.setAlarm(Alarm(time, this));
thePendAlarmCnt++;
}
void AlarmUser::sleepFor(Time delay) {
sleepTill(TheClock + delay);
}
void AlarmUser::cancelAlarms() {
if (thePendAlarmCnt)
TheAlarmClock.cancelAll(this);
Assert(!thePendAlarmCnt);
}
/* AlarmClock */
AlarmClock::AlarmClock() {
}
void AlarmClock::setAlarm(const Alarm &alarm) {
if (alarm)
theQueue.add(alarm);
}
void AlarmClock::cancelAll(const AlarmUser *sleeper) {
for (int i = theQueue.count()-1; i >= 0 && sleeper->alarmWaiting(); --i) {
if (theQueue.at(i).sleeper() == sleeper)
theQueue.at(i).snooze();
}
}
// rings all ready alarms
void AlarmClock::ring() {
// process alarms that were current at the call time only
for (int c = theQueue.count(); c && !theQueue.empty(); --c) {
if (const Alarm &alarm = theQueue.top()) {
if (alarm.time() <= theCurTime) {
static Time lastRing;
Assert(lastRing <= alarm.time());
lastRing = alarm.time();
theQueue.shift().ring();
} else
break; // not ready yet
} else {
theQueue.skip();
}
}
}
void AlarmClock::update(Time curTime) {
Clock::update(curTime);
ring();
}
// must be called only for an alarm clock that is on
Time AlarmClock::timeLeft() const {
Assert(!theQueue.empty());
if (const Alarm &alarm = theQueue.top())
return alarm.time() - theCurTime;
Assert(false); // timeLeft() must be called only for set alarm clock
return Time();
}
bool AlarmClock::on() {
while (!theQueue.empty() && !theQueue.top())
theQueue.skip();
return !theQueue.empty();
}
syntax highlighted by Code2HTML, v. 0.9.1