1 /*******************************************************************
2 uLan Utilities Library - C library of basic reusable constructions
4 ul_htimer.h - hierarchical timer basic declarations
6 (C) Copyright 2003-2009 by Pavel Pisa - Originator
8 The uLan utilities library can be used, copied and modified under
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.
20 See files COPYING and README for details.
22 *******************************************************************/
27 #include "ul_htimdefs.h"
30 #ifndef UL_HTIMER_WITH_HPTREE
32 #else /*UL_HTIMER_WITH_HPTREE*/
33 #include "ul_hptree.h"
34 #endif /*UL_HTIMER_WITH_HPTREE*/
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
45 * This is basic type useful to define more complete timer types
47 typedef struct ul_htim_node {
48 #ifndef UL_HTIMER_WITH_HPTREE
50 #else /*UL_HTIMER_WITH_HPTREE*/
52 #endif /*UL_HTIMER_WITH_HPTREE*/
53 ul_htim_time_t expires;
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
62 * This is basic type useful to define more complete timer queues types
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*/
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);
77 #ifndef UL_HTIMER_WITH_HPTREE
78 void ul_htim_queue_init_root_field(ul_htim_queue_t *queue);
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*/
86 #endif /*UL_HTIMER_INC_FROM_BASE*/
89 ul_htim_queue_inline_first(ul_htim_queue_t *queue, ul_htim_node_t **phtim)
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);
98 #else /*UL_HTIMER_WITH_HPTREE*/
99 int ul_htim_queue_init_root_field(ul_htim_queue_t *queue);
102 ul_htim_queue_init_detached(ul_htim_node_t *htim)
103 #ifndef UL_HTIMER_INC_FROM_BASE
105 #else /*UL_HTIMER_INC_FROM_BASE*/
107 #endif /*UL_HTIMER_INC_FROM_BASE*/
110 ul_htim_queue_inline_first(ul_htim_queue_t *queue, ul_htim_node_t **phtim)
112 if(!queue->timers.count) return 0;
113 *phtim=UL_CONTAINEROF(queue->timers.heaparr[ul_hpt_first_i],ul_htim_node_t,node);
116 #endif /*UL_HTIMER_WITH_HPTREE*/
118 #define UL_HTIMER_DEC_SCOPE(cust_scope, cust_prefix, cust_queue_t, cust_timer_t, \
119 cust_queue_field, cust_timer_field) \
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);\
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); \
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); \
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;\
139 cust_prefix##_init_detached(cust_timer_t *timer){\
140 ul_htim_queue_init_detached(&timer->cust_timer_field);\
143 cust_prefix##_set_expire(cust_timer_t *timer, ul_htim_time_t expire){\
144 timer->cust_timer_field.expires=expire;\
146 static inline ul_htim_time_t \
147 cust_prefix##_get_expire(cust_timer_t *timer){\
148 return timer->cust_timer_field.expires;\
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)
156 #define UL_HTIMER_IMP(cust_prefix, cust_queue_t, cust_timer_t, \
157 cust_queue_field, cust_timer_field) \
159 void cust_prefix##_init_queue(cust_queue_t *queue)\
161 ul_htim_queue_init_root_field(&queue->cust_queue_field);\
162 queue->cust_queue_field.first_changed=0;\
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))\
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);\
173 int cust_prefix##_next_expire(cust_queue_t *queue, ul_htim_time_t *pnext_time)\
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))\
179 *pnext_time=htim_node->expires;\
183 /*===========================================================*/
184 /* Standard timer (ul_htimer) */
186 #ifdef UL_HTIMER_WITH_STD_TYPE
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
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.
198 typedef struct ul_htimer {
200 ul_htimer_fnc_t *function;
201 ul_htimer_fnc_data_t data;
202 UL_HTIMER_USER_FIELDS
206 * struct ul_htimer_queue - Standard timer queue
207 * @htim_queue: the structure wraps &ul_htim_queue structure
209 * This is standard timer type, which requires @data casting
212 typedef struct ul_htimer_queue {
213 ul_htim_queue_t htim_queue;
216 UL_HTIMER_DEC(ul_htimer, ul_htimer_queue_t, ul_htimer_t, htim_queue, htim)
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);
231 #endif /*UL_HTIMER_WITH_STD_TYPE*/
233 /*===========================================================*/
234 /* Standard timer support to provide default root timer */
236 #ifdef UL_HTIMER_WITH_STD_TYPE
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;
245 extern ul_root_htimer_ops_t *ul_root_htimer_ops;
246 extern ul_root_htimer_ops_t *ul_root_htimer_ops_compile_default;
248 int ul_root_htimer_init(int options, void *context);
250 static inline ul_htimer_queue_t *ul_root_htimer_get(int options, void *context)
252 return ul_root_htimer_ops->timer_root_get(options, context);
255 static inline void ul_root_htimer_put(ul_htimer_queue_t *queue)
257 ul_root_htimer_ops->timer_root_put(queue);
260 static inline int ul_root_htimer_current_time(int options, ul_htim_time_t *htimer_time)
262 return ul_root_htimer_ops->current_time(options, htimer_time);
265 int ul_root_htimer_add(ul_htimer_t *timer);
267 int ul_root_htimer_detach(ul_htimer_t *timer);
268 #endif /*UL_HTIMER_WITH_STD_TYPE*/
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)
278 static inline int ul_ms2htimdiff(ul_htim_diff_t *htimdiff, const ul_msdiff_t *ms)
284 static inline int ul_htime2mstime(ul_mstime_t *ms, const ul_htim_time_t *htime)
290 static inline int ul_mstime2htime(ul_htim_time_t *htime, const ul_mstime_t *ms)
296 static inline int ul_htime_sub2ms(ul_msdiff_t *ms, const ul_htim_time_t *htimto,
297 const ul_htim_time_t *htimfrom)
299 ul_htim_diff_t htimdiff = *htimto - *htimfrom;
300 return ul_htimdiff2ms(ms, &htimdiff);
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)
306 *diff = *htimto - *htimfrom;
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)
313 *sum = *htimfrom + *diff;
317 #endif /*UL_HTIMER_WITH_STD_TYPE*/
319 //ul_mstime_t ul_mstime_last;
320 //ul_mstime_t ul_mstime_next;
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);
328 #endif /*UL_HTIMER_WITH_MSTIME*/
334 #endif /* _UL_HTIMER_H */