]> git.buserror.net Git - polintos/scott/priv.git/blob - include/c++/kernel/time.h
Initial checkin from Perforce.
[polintos/scott/priv.git] / include / c++ / kernel / time.h
1 #ifndef _KERNEL_TIME_H
2 #define _KERNEL_TIME_H
3
4 #include <kernel/kernel.h>
5 #include <System/Time.h>
6 #include <util/heap.h>
7 #include <util/spinlock.h>
8
9 namespace Time {
10         static inline void fix_time_add(System::Time::Time &time)
11         {
12                 if (time.nanos >= 1000000000) {
13                         time.nanos -= 1000000000;
14                         time.seconds++;
15                 }
16         }
17
18         static inline void fix_time_sub(System::Time::Time &time)
19         {
20                 if ((int32_t)time.nanos < 0) {
21                         time.nanos += 1000000000;
22                         time.seconds--;
23                 }
24         }
25 }
26
27 static inline long operator < (const System::Time::Time &left,
28                                const System::Time::Time &right)
29 {
30         return left.seconds - right.seconds < 0 ||
31                (left.seconds == right.seconds &&
32                 left.nanos < right.nanos);
33 }
34
35 static inline long operator == (const System::Time::Time &left,
36                                 const System::Time::Time &right)
37 {
38         return left.seconds == right.seconds &&
39                left.nanos == right.nanos;
40 }
41
42 static inline long operator != (const System::Time::Time &left,
43                                 const System::Time::Time &right)
44 {
45         return left.seconds != right.seconds ||
46                left.nanos != right.nanos;
47 }
48
49 static inline System::Time::Time operator +(const System::Time::Time &left,
50                                             const System::Time::Time &right)
51 {
52         System::Time::Time ret;
53
54         ret.seconds = left.seconds + right.seconds;
55         ret.nanos = left.nanos + right.nanos;
56         
57         Time::fix_time_add(ret);
58         return ret;
59 }
60
61 static inline System::Time::Time &operator +=(System::Time::Time &left,
62                                               const System::Time::Time &right)
63 {
64         left.seconds += right.seconds;
65         left.nanos += right.nanos;
66         
67         Time::fix_time_add(left);
68         return left;
69 }
70
71 static inline System::Time::Time operator -(const System::Time::Time &left,
72                                             const System::Time::Time &right)
73 {
74         System::Time::Time ret;
75
76         ret.seconds = left.seconds - right.seconds;
77         ret.nanos = left.nanos - right.nanos;
78         
79         Time::fix_time_sub(ret);
80         return ret;
81 }
82
83 static inline System::Time::Time &operator -=(System::Time::Time &left,
84                                               const System::Time::Time &right)
85 {
86         left.seconds -= right.seconds;
87         left.nanos -= right.nanos;
88         
89         Time::fix_time_sub(left);
90         return left;
91 }
92
93 static inline System::Time::Time operator +(const System::Time::Time &left,
94                                             uint32_t right)
95 {
96         System::Time::Time ret;
97
98         ret.seconds = left.seconds;
99         ret.nanos = left.nanos + right;
100         
101         Time::fix_time_add(ret);
102         return ret;
103 }
104
105 static inline System::Time::Time &operator +=(System::Time::Time &left,
106                                               uint32_t right)
107 {
108         left.nanos += right;
109         
110         Time::fix_time_add(left);
111         return left;
112 }
113
114 static inline System::Time::Time operator -(const System::Time::Time &left,
115                                             uint32_t right)
116 {
117         System::Time::Time ret;
118
119         ret.seconds = left.seconds;
120         ret.nanos = left.nanos - right;
121         
122         Time::fix_time_sub(ret);
123         return ret;
124 }
125
126 static inline System::Time::Time &operator -=(System::Time::Time &left,
127                                               uint32_t right)
128 {
129         left.nanos -= right;
130         
131         Time::fix_time_sub(left);
132         return left;
133 }
134
135 namespace Time {
136         typedef System::Time::Clock Clock;
137         typedef System::Time::Time Time;
138         typedef System::Time::ITime ITime;
139         typedef System::Time::Timer Timer;
140         typedef System::Time::ITimer ITimer;
141
142         using namespace Lock;
143         struct TimerEntry;
144
145         class TimerMux {
146                 Util::Heap<TimerEntry> heap;
147                 SpinLock lock;
148                 Clock clock;
149                 Timer parent;
150
151         public:
152                 TimerMux(Clock CLOCK, Timer PARENT) :
153                 clock(CLOCK), parent(PARENT)
154                 {
155                 }
156         
157                 void arm(TimerEntry *entry, Time expiry);
158                 void disarm(TimerEntry *entry);
159                 void run();
160         };
161
162         struct TimerEntry {
163                 Util::Heap<TimerEntry>::Node heap_node;
164                 Time expiry;
165                 TimerMux *mux;
166                 
167                 #include _KERNEL_SERVER(time/timer/Time/TimerEntry.h)
168
169                 TimerEntry(TimerMux *MUX = NULL) : mux(MUX)
170                 {
171                         init_iface();
172                         
173                         expiry.seconds = 0;
174                         expiry.nanos = 0;
175                 }
176
177                 virtual ~TimerEntry()
178                 {
179                 }
180
181                 void arm(Time expiry)
182                 {
183                         mux->arm(this, expiry);
184                 }
185                 
186                 void disarm()
187                 {
188                         mux->disarm(this);
189                 }
190                 
191                 void get_expiry(Time *ret, uint8_t *was_armed)
192                 {
193                         if (!ret || !was_armed) {
194                                 // FIXME: throw exception
195                                 return;
196                         }
197                         
198                         if (is_armed()) {
199                                 *ret = expiry;
200                                 *was_armed = 1;
201                         } else {
202                                 *was_armed = 0;
203                         }
204                 }
205         
206                 long operator < (TimerEntry &other)
207                 {
208                         return expiry < other.expiry;
209                 }
210                 
211                 bool is_armed()
212                 {
213                         return heap_node.is_on_heap();
214                 }
215                 
216                 void set_action(System::Events::Event *event);
217                 
218                 // This can be overridden in low-level code (specifically
219                 // the kernel) to execute the action synchronously,
220                 // inside the timer critical section.  Most code should
221                 // (and non-C++ code must) use set_action instead.
222                 
223                 virtual void action();
224         };
225 }
226
227 #endif