]> git.tdb.fi Git - libs/core.git/blob - source/time/timer.cpp
Rewrite Time::Timer to not force the use of a thread, so it's more useful.
[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         slots(slot_compare)
17 { }
18
19 Timer::~Timer()
20 {
21         while(!slots.empty())
22         {
23                 delete slots.top();
24                 slots.pop();
25         }
26 }
27
28 Timer::Slot &Timer::add(const TimeDelta &td)
29 {
30         Slot *s=new Slot(td);
31         mutex.lock();
32         slots.push(s);
33         mutex.unlock();
34         sem.signal();
35         return *s;
36 }
37
38 Timer::Slot &Timer::add(const TimeStamp &ts)
39 {
40         Slot *s=new Slot(ts);
41         mutex.lock();
42         slots.push(s);
43         mutex.unlock();
44         sem.signal();
45         return *s;
46 }
47
48 void Timer::tick(bool block)
49 {
50         if(slots.empty())
51         {
52                 if(block)
53                         sem.wait();
54                 return;
55         }
56
57         mutex.lock();
58         Slot *next=slots.top();
59         mutex.unlock();
60
61         const TimeStamp &stamp=next->get_timeout();
62         const TimeStamp t=now();
63         if(stamp<=t || (block && sem.wait(stamp-t)==1))
64         {
65                 slots.pop();
66                 if(next->signal_timeout.emit() && next->increment())
67                         slots.push(next);
68                 else
69                         delete next;
70         }
71 }
72
73 bool Timer::slot_compare(Slot *a, Slot *b)
74 {
75         return *a<*b;
76 }
77
78
79 Timer::Slot::Slot(const TimeDelta &td):
80         interval(td),
81         timeout(now()+interval)
82 { }
83
84 Timer::Slot::Slot(const TimeStamp &ts):
85         timeout(ts)
86 { }
87
88 bool Timer::Slot::increment()
89 {
90         if(!interval)
91                 return false;
92         timeout+=interval;
93         return true;
94 }
95
96 bool Timer::Slot::operator<(const Slot &other) const
97 {
98         return timeout<other.timeout;
99 }
100
101 } // namespace Time
102 } // namespace Msp