]> rtime.felk.cvut.cz Git - ulut.git/blob - ulut/ul_htimer.h
uLUt: do not include malloc.h, use stdlib.h through ul_utmalloc.h.
[ulut.git] / ulut / ul_htimer.h
1 /*******************************************************************
2   uLan Utilities Library - C library of basic reusable constructions
3
4   ul_htimer.h  - hierarchical timer basic declarations
5
6   (C) Copyright 2003-2009 by Pavel Pisa - Originator
7
8   The uLan utilities library can be used, copied and modified under
9   next licenses
10     - GPL - GNU General Public License
11     - LGPL - GNU Lesser General Public License
12     - MPL - Mozilla Public License
13     - and other licenses added by project originators
14   Code can be modified and re-distributed under any combination
15   of the above listed licenses. If contributor does not agree with
16   some of the licenses, he/she can delete appropriate line.
17   Warning, if you delete all lines, you are not allowed to
18   distribute source code and/or binaries utilizing code.
19   
20   See files COPYING and README for details.
21
22  *******************************************************************/
23
24 #ifndef _UL_HTIMER_H
25 #define _UL_HTIMER_H
26
27 #include "ul_htimdefs.h"
28
29 #include "ul_list.h"
30 #ifndef UL_HTIMER_WITH_HPTREE
31  #include "ul_gavl.h"
32 #else /*UL_HTIMER_WITH_HPTREE*/
33  #include "ul_hptree.h"
34 #endif /*UL_HTIMER_WITH_HPTREE*/
35
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39
40 /**
41  * struct ul_htim_node - Timer queue entry base structure
42  * @node:    regular GAVL node structure for insertion into 
43  * @expires: time to trigger timer in &ul_htim_time_t type defined resolution
44  *
45  * This is basic type useful to define more complete timer types
46  */
47 typedef struct ul_htim_node {
48  #ifndef UL_HTIMER_WITH_HPTREE
49   gavl_node_t    node;
50  #else /*UL_HTIMER_WITH_HPTREE*/
51   ul_hpt_node_t    node;
52  #endif /*UL_HTIMER_WITH_HPTREE*/
53   ul_htim_time_t expires;
54 } ul_htim_node_t;
55
56 /**
57  * struct ul_htim_queue - Timer queue head/root base structure
58  * @timers:  root of FLES GAVL tree of timer entries 
59  * @first_changed: flag, which is set after each add, detach operation
60  *                 which concerning of firsts scheduled timer
61  *
62  * This is basic type useful to define more complete timer queues types
63  */
64 typedef struct ul_htim_queue {
65  #ifndef UL_HTIMER_WITH_HPTREE
66   gavl_fles_int_root_field_t timers;
67  #else /*UL_HTIMER_WITH_HPTREE*/
68   ul_hpt_root_field_t timers;
69  #endif /*UL_HTIMER_WITH_HPTREE*/
70   int first_changed;
71 } ul_htim_queue_t;
72
73 int ul_htim_queue_insert(ul_htim_queue_t *queue, ul_htim_node_t *htim);
74 int ul_htim_queue_delete(ul_htim_queue_t *queue, ul_htim_node_t *htim);
75 ul_htim_node_t *ul_htim_queue_cut_first(ul_htim_queue_t *queue);
76
77 #ifndef UL_HTIMER_WITH_HPTREE
78 void ul_htim_queue_init_root_field(ul_htim_queue_t *queue);
79
80 static inline void 
81 ul_htim_queue_init_detached(ul_htim_node_t *htim)
82 #ifndef UL_HTIMER_INC_FROM_BASE
83   {htim->node.parent=NULL;}
84 #else /*UL_HTIMER_INC_FROM_BASE*/
85   ;
86 #endif /*UL_HTIMER_INC_FROM_BASE*/
87
88 static inline int
89 ul_htim_queue_inline_first(ul_htim_queue_t *queue, ul_htim_node_t **phtim)
90 {
91   /*little faster equivalent to ul_htim_queue_first(&queue->cust_queue_field);*/
92   gavl_node_t *gavl_node=queue->timers.first;
93   if(!gavl_node) return 0;
94   *phtim=UL_CONTAINEROF(gavl_node,ul_htim_node_t,node);
95   return 1;
96 }
97
98 #else /*UL_HTIMER_WITH_HPTREE*/
99 int ul_htim_queue_init_root_field(ul_htim_queue_t *queue);
100
101 static inline void 
102 ul_htim_queue_init_detached(ul_htim_node_t *htim)
103 #ifndef UL_HTIMER_INC_FROM_BASE
104   {;}
105 #else /*UL_HTIMER_INC_FROM_BASE*/
106   ;
107 #endif /*UL_HTIMER_INC_FROM_BASE*/
108
109 static inline int
110 ul_htim_queue_inline_first(ul_htim_queue_t *queue, ul_htim_node_t **phtim)
111 {
112   if(!queue->timers.count) return 0;
113   *phtim=UL_CONTAINEROF(queue->timers.heaparr[ul_hpt_first_i],ul_htim_node_t,node);
114   return *phtim!=0;
115 }
116 #endif /*UL_HTIMER_WITH_HPTREE*/
117
118 #define UL_HTIMER_DEC_SCOPE(cust_scope, cust_prefix, cust_queue_t, cust_timer_t, \
119                 cust_queue_field, cust_timer_field) \
120 \
121 cust_scope void cust_prefix##_init_queue(cust_queue_t *queue);\
122 cust_scope cust_timer_t *cust_prefix##_cut_expired(cust_queue_t *queue, ul_htim_time_t *act_time);\
123 cust_scope int cust_prefix##_next_expire(cust_queue_t *queue, ul_htim_time_t *act_time);\
124 static inline int \
125 cust_prefix##_add(cust_queue_t *queue, cust_timer_t *timer){ \
126   return ul_htim_queue_insert(&queue->cust_queue_field, &timer->cust_timer_field); \
127 } \
128 static inline int \
129 cust_prefix##_detach(cust_queue_t *queue, cust_timer_t *timer){ \
130   return ul_htim_queue_delete(&queue->cust_queue_field, &timer->cust_timer_field); \
131 }\
132 static inline int \
133 cust_prefix##_first_changed(cust_queue_t *queue){\
134   int first_changed=queue->cust_queue_field.first_changed;\
135   queue->cust_queue_field.first_changed=0;\
136   return first_changed;\
137 }\
138 static inline void \
139 cust_prefix##_init_detached(cust_timer_t *timer){\
140   ul_htim_queue_init_detached(&timer->cust_timer_field);\
141 }\
142 static inline void \
143 cust_prefix##_set_expire(cust_timer_t *timer, ul_htim_time_t expire){\
144   timer->cust_timer_field.expires=expire;\
145 }\
146 static inline ul_htim_time_t \
147 cust_prefix##_get_expire(cust_timer_t *timer){\
148   return timer->cust_timer_field.expires;\
149 }
150
151 #define UL_HTIMER_DEC(cust_prefix, cust_queue_t, cust_timer_t, \
152                 cust_queue_field, cust_timer_field) \
153         UL_HTIMER_DEC_SCOPE(extern, cust_prefix, cust_queue_t, cust_timer_t, \
154                 cust_queue_field, cust_timer_field)
155
156 #define UL_HTIMER_IMP(cust_prefix, cust_queue_t, cust_timer_t, \
157                 cust_queue_field, cust_timer_field) \
158 \
159 void cust_prefix##_init_queue(cust_queue_t *queue)\
160 {\
161   ul_htim_queue_init_root_field(&queue->cust_queue_field);\
162   queue->cust_queue_field.first_changed=0;\
163 }\
164 cust_timer_t *cust_prefix##_cut_expired(cust_queue_t *queue, ul_htim_time_t *pact_time)\
165 { /*little faster equivalent to ul_htim_queue_first(&queue->cust_queue_field);*/\
166   ul_htim_node_t *htim_node;\
167   if(!ul_htim_queue_inline_first(&queue->cust_queue_field,&htim_node))\
168     return 0;\
169   if(ul_htimer_cmp_fnc(&htim_node->expires,pact_time)>0) return NULL;\
170   htim_node=ul_htim_queue_cut_first(&queue->cust_queue_field);\
171   return UL_CONTAINEROF(htim_node,cust_timer_t,cust_timer_field);\
172 }\
173 int cust_prefix##_next_expire(cust_queue_t *queue, ul_htim_time_t *pnext_time)\
174 {\
175   /*same as above, allows also new timers without "ul_gavlflesint.h" explicit inclussion */\
176   ul_htim_node_t *htim_node;\
177   if(!ul_htim_queue_inline_first(&queue->cust_queue_field,&htim_node))\
178     return 0;\
179   *pnext_time=htim_node->expires;\
180   return 1;\
181 }
182
183 /*===========================================================*/
184 /*  Standard timer (ul_htimer) */
185
186 #ifdef UL_HTIMER_WITH_STD_TYPE
187
188 /**
189  * struct ul_htimer - Standard timer entry with callback function
190  * @htim:     basic timer queue entry
191  * @function: user provided function to call at trigger time
192  * @data:     user selected data
193  *
194  * This is standard timer type, which requires @data casting
195  * in many cases. The type of @function field has to be declared
196  * in "ul_htimdefs.h" header file.
197  */
198 typedef struct ul_htimer {
199   ul_htim_node_t htim;
200   ul_htimer_fnc_t *function;
201   ul_htimer_fnc_data_t data;
202   UL_HTIMER_USER_FIELDS
203 } ul_htimer_t;
204
205 /**
206  * struct ul_htimer_queue - Standard timer queue
207  * @htim_queue: the structure wraps &ul_htim_queue structure
208  *
209  * This is standard timer type, which requires @data casting
210  * in many cases
211  */
212 typedef struct ul_htimer_queue {
213   ul_htim_queue_t htim_queue;
214 } ul_htimer_queue_t;
215
216 UL_HTIMER_DEC(ul_htimer, ul_htimer_queue_t, ul_htimer_t, htim_queue, htim) 
217
218 void ul_htimer_run_expired(ul_htimer_queue_t *queue, ul_htim_time_t *pact_time);
219 /* there are next usefull functions 
220  * void ul_htimer_init_queue(ul_htimer_queue_t *queue);
221  * int ul_htimer_add(ul_htimer_queue_t *queue, ul_htimer_t *timer);
222  * int ul_htimer_detach(ul_htimer_queue_t *queue, ul_htimer_t *timer);
223  * int ul_htimer_first_changed(ul_htimer_queue_t *queue);
224  * int ul_htimer_next_expire(ul_htimer_queue_t *queue, ul_htim_time_t *pnext_time);
225  * ul_htimer_t *ul_htimer_cut_expired(ul_htimer_queue_t *queue, ul_htim_time_t *pact_time);
226  * void ul_htimer_init_detached(ul_htimer_t *timer);
227  * void ul_htimer_set_expire(ul_htimer_t *timer, ul_htim_time_t expire);
228  * ul_htim_time_t ul_htimer_get_expire(ul_htimer_t *timer);
229  */
230
231 #endif /*UL_HTIMER_WITH_STD_TYPE*/
232
233 /*===========================================================*/
234 /*  Standard timer support to provide default root timer */
235
236 #ifdef UL_HTIMER_WITH_STD_TYPE
237
238 typedef struct ul_root_htimer_ops_t {
239   int (*timer_root_init)(int options, void *context) UL_ATTR_REENTRANT;
240   ul_htimer_queue_t *(*timer_root_get)(int options, void *context) UL_ATTR_REENTRANT;
241   void (*timer_root_put)(ul_htimer_queue_t *queue) UL_ATTR_REENTRANT;
242   int (*current_time)(int options, ul_htim_time_t *htimer_time) UL_ATTR_REENTRANT;
243 } ul_root_htimer_ops_t;
244
245 extern ul_root_htimer_ops_t *ul_root_htimer_ops;
246 extern ul_root_htimer_ops_t *ul_root_htimer_ops_compile_default;
247
248 int ul_root_htimer_init(int options, void *context);
249
250 static inline ul_htimer_queue_t *ul_root_htimer_get(int options, void *context)
251 {
252   return ul_root_htimer_ops->timer_root_get(options, context);
253 }
254
255 static inline void ul_root_htimer_put(ul_htimer_queue_t *queue)
256 {
257   ul_root_htimer_ops->timer_root_put(queue);
258 }
259
260 static inline int ul_root_htimer_current_time(int options, ul_htim_time_t *htimer_time)
261 {
262   return ul_root_htimer_ops->current_time(options, htimer_time);
263 }
264
265 int ul_root_htimer_add(ul_htimer_t *timer);
266
267 int ul_root_htimer_detach(ul_htimer_t *timer);
268 #endif /*UL_HTIMER_WITH_STD_TYPE*/
269
270 #ifdef UL_HTIMER_WITH_MSTIME
271 #ifdef UL_HTIMER_WITH_STD_TYPE
272 static inline int ul_htimdiff2ms(ul_msdiff_t *ms, const ul_htim_diff_t *htimdiff)
273 {
274   *ms = *htimdiff;
275   return 0;
276 }
277
278 static inline int ul_ms2htimdiff(ul_htim_diff_t *htimdiff, const ul_msdiff_t *ms)
279 {
280   *htimdiff = *ms;
281   return 0;
282 }
283
284 static inline int ul_htime2mstime(ul_mstime_t *ms, const ul_htim_time_t *htime)
285 {
286   *ms = *htime;
287   return 0;
288 }
289
290 static inline int ul_mstime2htime(ul_htim_time_t *htime, const ul_mstime_t *ms)
291 {
292   *htime = *ms;
293   return 0;
294 }
295
296 static inline int ul_htime_sub2ms(ul_msdiff_t *ms, const ul_htim_time_t *htimto,
297                                 const ul_htim_time_t *htimfrom)
298 {
299   ul_htim_diff_t htimdiff = *htimto - *htimfrom;
300   return ul_htimdiff2ms(ms, &htimdiff);
301 }
302
303 static inline int ul_htime_sub(ul_htim_diff_t *diff, const ul_htim_time_t *htimto,
304                                 const ul_htim_time_t *htimfrom)
305 {
306   *diff = *htimto - *htimfrom;
307   return 0;
308 }
309
310 static inline int ul_htime_add(ul_htim_time_t *sum, const ul_htim_time_t *htimfrom,
311                                 const ul_htim_diff_t *diff)
312 {
313   *sum = *htimfrom + *diff;
314   return 0;
315 }
316
317 #endif /*UL_HTIMER_WITH_STD_TYPE*/
318
319 //ul_mstime_t ul_mstime_last;
320 //ul_mstime_t ul_mstime_next;
321
322 void ul_mstime_now(ul_mstime_t *mstm);
323 //void ul_mstime_update(void);
324 //void ul_mstime_init(void);
325 void ul_get_log_time_str(char str[30]);
326 //void ul_compute_mstime_next(void);
327
328 #endif /*UL_HTIMER_WITH_MSTIME*/
329
330 #ifdef __cplusplus
331 } /* extern "C"*/
332 #endif
333
334 #endif /* _UL_HTIMER_H */