namespace Msp {
namespace Time {
-Timer::Timer():
- slots(slot_compare)
-{ }
-
Timer::~Timer()
{
- while(!slots.empty())
- {
- delete slots.top();
- slots.pop();
- }
+ for(set<SlotProxy>::iterator i=slots.begin(); i!=slots.end(); ++i)
+ delete i->slot;
}
Timer::Slot &Timer::add(const TimeDelta &td)
{
Slot *s=new Slot(td);
mutex.lock();
- slots.push(s);
+ slots.insert(s);
mutex.unlock();
sem.signal();
return *s;
Timer::Slot &Timer::add(const TimeStamp &ts)
{
Slot *s=new Slot(ts);
- mutex.lock();
- slots.push(s);
- mutex.unlock();
+ {
+ MutexLock l(mutex);
+ slots.insert(s);
+ }
sem.signal();
return *s;
}
+void Timer::cancel(Slot &slot)
+{
+ MutexLock l(mutex);
+ if(slots.erase(&slot))
+ delete &slot;
+}
+
void Timer::tick(bool block)
{
if(slots.empty())
{
if(block)
sem.wait();
- return;
+ else
+ return;
}
- mutex.lock();
- Slot *next=slots.top();
- mutex.unlock();
+ Slot *next;
+ {
+ MutexLock l(mutex);
+ next=slots.begin()->slot;
+ }
const TimeStamp &stamp=next->get_timeout();
const TimeStamp t=now();
if(stamp<=t || (block && sem.wait(stamp-t)==1))
{
- slots.pop();
+ slots.erase(slots.begin());
if(next->signal_timeout.emit() && next->increment())
- slots.push(next);
+ slots.insert(next);
else
delete next;
}
}
-bool Timer::slot_compare(Slot *a, Slot *b)
+TimeStamp Timer::get_next_timeout() const
{
- return *a<*b;
+ if(slots.empty())
+ return TimeStamp();
+ return slots.begin()->slot->get_timeout();
}
return true;
}
-bool Timer::Slot::operator<(const Slot &other) const
+
+Timer::SlotProxy::SlotProxy(Slot *s):
+ slot(s)
+{ }
+
+bool Timer::SlotProxy::operator<(const SlotProxy &sp) const
{
- return timeout<other.timeout;
+ return slot->get_timeout()<sp.slot->get_timeout();
}
} // namespace Time
#ifndef MSP_TIME_TIMER_H_
#define MSP_TIME_TIMER_H_
-#include <queue>
+#include <set>
#include <sigc++/sigc++.h>
#include "../core/mutex.h"
#include "../core/semaphore.h"
Slot(const TimeStamp &);
const TimeStamp &get_timeout() const { return timeout; }
bool increment();
- bool operator<(const Slot &) const;
};
private:
- typedef bool (*fSlotCompare)(Slot *, Slot *);
+ struct SlotProxy
+ {
+ Slot *slot;
+
+ SlotProxy(Slot *);
+ bool operator<(const SlotProxy &) const;
+ };
- std::priority_queue<Slot *, std::vector<Slot *>, fSlotCompare> slots;
+ std::set<SlotProxy> slots;
Semaphore sem;
Mutex mutex;
public:
- Timer();
~Timer();
/**
*/
Slot &add(const TimeStamp &);
+ /**
+ Cancels a previously added timer.
+ */
+ void cancel(Slot &);
+
/**
Checks all timers, executing any that have timed out. If block is true,
waits until one times out.
won't return until a timer is added from another thread.
*/
void tick(bool block=true);
-private:
- static bool slot_compare(Slot *, Slot *);
+
+ TimeStamp get_next_timeout() const;
};
} // namespace Time