]> git.tdb.fi Git - libs/core.git/blob - source/time/timer.cpp
Allow canceling timers
[libs/core.git] / source / time / timer.cpp
1 /*
2 This file is part of libmspcore     
3 Copyright © 2006  Mikko Rasa, Mikkosoft Productions
4 Distributed under the LGPL
5 */
6
7 #include "timer.h"
8 #include "utils.h"
9
10 using namespace std;
11
12 namespace Msp {
13 namespace Time {
14
15 Timer::~Timer()
16 {
17         for(set<SlotProxy>::iterator i=slots.begin(); i!=slots.end(); ++i)
18                 delete i->slot;
19 }
20
21 Timer::Slot &Timer::add(const TimeDelta &td)
22 {
23         Slot *s=new Slot(td);
24         mutex.lock();
25         slots.insert(s);
26         mutex.unlock();
27         sem.signal();
28         return *s;
29 }
30
31 Timer::Slot &Timer::add(const TimeStamp &ts)
32 {
33         Slot *s=new Slot(ts);
34         {
35                 MutexLock l(mutex);
36                 slots.insert(s);
37         }
38         sem.signal();
39         return *s;
40 }
41
42 void Timer::cancel(Slot &slot)
43 {
44         MutexLock l(mutex);
45         if(slots.erase(&slot))
46                 delete &slot;
47 }
48
49 void Timer::tick(bool block)
50 {
51         if(slots.empty())
52         {
53                 if(block)
54                         sem.wait();
55                 else
56                         return;
57         }
58
59         Slot *next;
60         {
61                 MutexLock l(mutex);
62                 next=slots.begin()->slot;
63         }
64
65         const TimeStamp &stamp=next->get_timeout();
66         const TimeStamp t=now();
67         if(stamp<=t || (block && sem.wait(stamp-t)==1))
68         {
69                 slots.erase(slots.begin());
70                 if(next->signal_timeout.emit() && next->increment())
71                         slots.insert(next);
72                 else
73                         delete next;
74         }
75 }
76
77 TimeStamp Timer::get_next_timeout() const
78 {
79         if(slots.empty())
80                 return TimeStamp();
81         return slots.begin()->slot->get_timeout();
82 }
83
84
85 Timer::Slot::Slot(const TimeDelta &td):
86         interval(td),
87         timeout(now()+interval)
88 { }
89
90 Timer::Slot::Slot(const TimeStamp &ts):
91         timeout(ts)
92 { }
93
94 bool Timer::Slot::increment()
95 {
96         if(!interval)
97                 return false;
98         timeout+=interval;
99         return true;
100 }
101
102
103 Timer::SlotProxy::SlotProxy(Slot *s):
104         slot(s)
105 { }
106
107 bool Timer::SlotProxy::operator<(const SlotProxy &sp) const
108 {
109         return slot->get_timeout()<sp.slot->get_timeout();
110 }
111
112 } // namespace Time
113 } // namespace Msp