1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>KLone: timer.c Source File</title>
<link href="kl.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.9.1 -->
<div class="qindex"><a class="qindex" href="index.html">Main Page</a> | <a class="qindex" href="modules.html">Modules</a> | <a class="qindex" href="annotated.html">Data Structures</a> | <a class="qindex" href="dirs.html">Directories</a> | <a class="qindex" href="files.html">File List</a> | <a class="qindex" href="functions.html">Data Fields</a> | <a class="qindex" href="globals.html">Globals</a></div>
<div class="nav">
<a class="el" href="dir_000000.html">src</a> / <a class="el" href="dir_000001.html">libutils</a></div>
<h1>timer.c</h1><a href="timer_8c.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment">00001 <span class="comment">/*</span>
00002 <span class="comment"> * Copyright (c) 2005, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com></span>
00003 <span class="comment"> * All rights reserved.</span>
00004 <span class="comment"> *</span>
00005 <span class="comment"> * This file is part of KLone, and as such it is subject to the license stated</span>
00006 <span class="comment"> * in the LICENSE file which you have received as part of this distribution.</span>
00007 <span class="comment"> *</span>
00008 <span class="comment"> * $Id: timer.c,v 1.15 2006/04/22 13:59:01 tat Exp $</span>
00009 <span class="comment"> */</span>
00010
00011 <span class="preprocessor">#include "klone_conf.h"</span>
00012 <span class="preprocessor">#include <time.h></span>
00013 <span class="preprocessor">#include <unistd.h></span>
00014 <span class="preprocessor">#include <signal.h></span>
00015 <span class="preprocessor">#include <<a class="code" href="timer_8h.html">klone/timer.h</a>></span>
00016 <span class="preprocessor">#include <<a class="code" href="utils_8h.html">klone/utils.h</a>></span>
00017 <span class="preprocessor">#include <u/libu.h></span>
00018
00019 <span class="preprocessor">#ifdef OS_WIN</span>
00020 <span class="preprocessor"></span><span class="preprocessor">#include <windows.h></span>
00021 <span class="preprocessor">#endif</span>
00022 <span class="preprocessor"></span>
00023 <a class="code" href="field_8h.html#a5">TAILQ_HEAD</a>(talarm_list_s, talarm_s);
<a name="l00024"></a><a class="code" href="timer_8c.html#a0">00024</a> <span class="keyword">typedef</span> <span class="keyword">struct </span>talarm_list_s <a class="code" href="timer_8c.html#a0">talarm_list_t</a>;
00025
<a name="l00026"></a><a class="code" href="timer_8c.html#a1">00026</a> <span class="keyword">typedef</span> void (*timerm_cb_t)(int);
00027
00028 <span class="keyword">struct </span>talarm_s
00029 {
00030 TAILQ_ENTRY(talarm_s) np; <span class="comment">/* next & prev pointers */</span>
00031 <a class="code" href="timer_8h.html#a0">timerm_t</a> *timer; <span class="comment">/* timerm_t that owns the alarm */</span>
00032 time_t expire; <span class="comment">/* when to fire the alarm */</span>
00033 <a class="code" href="timer_8h.html#a2">talarm_cb_t</a> cb; <span class="comment">/* alarm callback */</span>
00034 <span class="keywordtype">void</span> *arg; <span class="comment">/* cb opaque argument */</span>
00035 };
00036
00037 <span class="keyword">struct </span>timerm_s
00038 {
00039 <a class="code" href="timer_8c.html#a0">talarm_list_t</a> alist; <span class="comment">/* alarm list */</span>
00040
00041 <span class="preprocessor">#ifdef OS_WIN</span>
00042 <span class="preprocessor"></span> CRITICAL_SECTION cs;
00043 time_t next; <span class="comment">/* next timestamp */</span>
00044 HANDLE hthread; <span class="comment">/* thread handle */</span>
00045 DWORD tid; <span class="comment">/* thread id */</span>
00046 <span class="preprocessor">#endif</span>
00047 <span class="preprocessor"></span>};
00048
00049 <span class="comment">/* this must be a singleton */</span>
00050 <span class="keyword">static</span> <a class="code" href="timer_8h.html#a0">timerm_t</a> *timer = NULL;
00051
00052 <span class="keyword">static</span> <span class="keywordtype">int</span> timerm_set_alarm(<span class="keywordtype">int</span> timeout)
00053 {
00054 <span class="preprocessor">#ifdef OS_UNIX</span>
00055 <span class="preprocessor"></span> <span class="comment">/* if timeout == 0 disable the alarm */</span>
00056 alarm(timeout);
00057 <span class="preprocessor">#else</span>
00058 <span class="preprocessor"></span> <span class="keywordflow">if</span>(timeout > 0)
00059 timer->next = time(0) + timeout;
00060 <span class="keywordflow">else</span>
00061 timer->next = NULL;
00062 <span class="preprocessor">#endif</span>
00063 <span class="preprocessor"></span>
00064 <span class="keywordflow">return</span> 0;
00065 }
00066
00067 <span class="keyword">static</span> <span class="keywordtype">int</span> timerm_set_next(<span class="keywordtype">void</span>)
00068 {
00069 <a class="code" href="timer_8h.html#a1">talarm_t</a> *al = NULL;
00070 time_t now = time(0);
00071
00072 <span class="keywordflow">if</span>((al = TAILQ_FIRST(&timer->alist)) == NULL)
00073 timerm_set_alarm(0); <span class="comment">/* disable the alarm */</span>
00074 <span class="keywordflow">else</span>
00075 timerm_set_alarm(<a class="code" href="utils_8h.html#a1">MAX</a>(1, al->expire - now));
00076
00077 <span class="keywordflow">return</span> 0;
00078 }
00079
<a name="l00080"></a><a class="code" href="timer_8c.html#a6">00080</a> <span class="keywordtype">void</span> <a class="code" href="timer_8c.html#a6">timerm_sigalrm</a>(<span class="keywordtype">int</span> sigalrm)
00081 {
00082 <a class="code" href="timer_8h.html#a1">talarm_t</a> *al = NULL, *next = NULL;
00083 <span class="keywordtype">int</span> expire;
00084
00085 u_unused_args(sigalrm);
00086
00087 dbg_err_if(timer == NULL);
00088
00089 <span class="keywordflow">for</span>(;;)
00090 {
00091 <span class="comment">/* get the topmost item and remove it from the list */</span>
00092 al = TAILQ_FIRST(&timer->alist);
00093 dbg_err_if(al == NULL);
00094
00095 expire = al->expire;
00096
00097 TAILQ_REMOVE(&timer->alist, al, np);
00098
00099 <span class="comment">/* call the callback function */</span>
00100 al->cb(al, al->arg);
00101
00102 <span class="comment">/* handle alarms with the same expiration date */</span>
00103 next = TAILQ_FIRST(&timer->alist);
00104 <span class="keywordflow">if</span>(next && next->expire == expire)
00105 <span class="keywordflow">continue</span>;
00106
00107 <span class="keywordflow">break</span>;
00108 }
00109
00110 <span class="comment">/* prepare for the next alarm */</span>
00111 <span class="keywordflow">if</span>(TAILQ_FIRST(&timer->alist))
00112 timerm_set_next();
00113
00114 err:
00115 <span class="keywordflow">return</span>;
00116 }
00117
00118 <span class="keyword">static</span> <span class="keywordtype">int</span> timerm_block_alarms(<span class="keywordtype">void</span>)
00119 {
00120 <span class="preprocessor">#ifdef OS_UNIX</span>
00121 <span class="preprocessor"></span> dbg_err_if(<a class="code" href="utils_8h.html#a39">u_sig_block</a>(SIGALRM));
00122 <span class="preprocessor">#endif</span>
00123 <span class="preprocessor"></span>
00124 <span class="preprocessor">#ifdef OS_WIN</span>
00125 <span class="preprocessor"></span> EnterCriticalSection(&timer->cs);
00126 <span class="preprocessor">#endif</span>
00127 <span class="preprocessor"></span>
00128 <span class="keywordflow">return</span> 0;
00129 err:
00130 <span class="keywordflow">return</span> ~0;
00131 }
00132
00133 <span class="keyword">static</span> <span class="keywordtype">int</span> timerm_unblock_alarms(<span class="keywordtype">void</span>)
00134 {
00135 <span class="preprocessor">#ifdef OS_UNIX</span>
00136 <span class="preprocessor"></span> dbg_err_if(<a class="code" href="utils_8h.html#a40">u_sig_unblock</a>(SIGALRM));
00137 <span class="preprocessor">#endif</span>
00138 <span class="preprocessor"></span>
00139 <span class="preprocessor">#ifdef OS_WIN</span>
00140 <span class="preprocessor"></span> LeaveCriticalSection(&timer->cs);
00141 <span class="preprocessor">#endif</span>
00142 <span class="preprocessor"></span>
00143 <span class="keywordflow">return</span> 0;
00144 err:
00145 <span class="keywordflow">return</span> ~0;
00146 }
00147
00148 <span class="keyword">static</span> <span class="keywordtype">int</span> timerm_free(<a class="code" href="timer_8h.html#a0">timerm_t</a> *t)
00149 {
00150 <a class="code" href="timer_8h.html#a1">talarm_t</a> *a = NULL;
00151
00152 dbg_return_if (t == NULL, ~0);
00153
00154 <span class="keywordflow">if</span>(t)
00155 {
00156 <span class="keywordflow">while</span>((a = TAILQ_FIRST(&t->alist)) != NULL)
00157 dbg_if(<a class="code" href="timer_8h.html#a4">timerm_del</a>(a));
00158
00159 U_FREE(t);
00160 }
00161
00162 <span class="keywordflow">return</span> 0;
00163 }
00164
00165 <span class="preprocessor">#ifdef OS_WIN</span>
00166 <span class="preprocessor"></span><span class="keyword">static</span> DWORD WINAPI thread_func(LPVOID param)
00167 {
00168 <span class="keywordflow">for</span>(;;Sleep(250))
00169 {
00170 <span class="keywordflow">if</span>(timer->next == NULL)
00171 <span class="keywordflow">continue</span>;
00172
00173 <span class="keywordflow">if</span>((timer->next - time(0)) <= 0)
00174 <a class="code" href="timer_8c.html#a6">timerm_sigalrm</a>(0); <span class="comment">/* raise the alarm */</span>
00175 }
00176
00177 <span class="keywordflow">return</span> 0;
00178 }
00179 <span class="preprocessor">#endif</span>
00180 <span class="preprocessor"></span>
00181 <span class="keyword">static</span> <span class="keywordtype">int</span> timerm_create(<a class="code" href="timer_8h.html#a0">timerm_t</a> **pt)
00182 {
00183 <a class="code" href="timer_8h.html#a0">timerm_t</a> *t = NULL;
00184
00185 dbg_return_if (pt == NULL, ~0);
00186
00187 t = u_zalloc(<span class="keyword">sizeof</span>(<a class="code" href="timer_8h.html#a0">timerm_t</a>));
00188 dbg_err_if(t == NULL);
00189
00190 TAILQ_INIT(&t->alist);
00191
00192 <span class="preprocessor">#ifdef OS_WIN</span>
00193 <span class="preprocessor"></span> InitializeCriticalSection(&t->cs);
00194
00195 dbg_err_if((t->hthread = CreateThread(NULL, 0, thread_func, NULL, 0,
00196 &t->tid)) == NULL);
00197 <span class="preprocessor">#endif</span>
00198 <span class="preprocessor"></span>
00199 *pt = t;
00200
00201 <span class="keywordflow">return</span> 0;
00202 err:
00203 <span class="keywordflow">if</span>(t)
00204 timerm_free(t);
00205 <span class="keywordflow">return</span> ~0;
00206 }
00207
<a name="l00208"></a><a class="code" href="timer_8h.html#a3">00208</a> <span class="keywordtype">int</span> <a class="code" href="timer_8h.html#a3">timerm_add</a>(<span class="keywordtype">int</span> secs, talarm_cb_t cb, <span class="keywordtype">void</span> *arg, <a class="code" href="timer_8h.html#a1">talarm_t</a> **pa)
00209 {
00210 <a class="code" href="timer_8h.html#a1">talarm_t</a> *al = NULL;
00211 <a class="code" href="timer_8h.html#a1">talarm_t</a> *item = NULL;
00212 time_t now = time(0);
00213
00214 dbg_return_if (cb == NULL, ~0);
00215 dbg_return_if (pa == NULL, ~0);
00216
00217 <span class="keywordflow">if</span>(timer == NULL)
00218 {
00219 dbg_err_if(timerm_create(&timer));
00220 <span class="preprocessor"> #ifdef OS_UNIX</span>
00221 <span class="preprocessor"></span> dbg_err_if(<a class="code" href="group__u__t.html#ga40">u_signal</a>(SIGALRM, <a class="code" href="timer_8c.html#a6">timerm_sigalrm</a>));
00222 <span class="preprocessor"> #endif</span>
00223 <span class="preprocessor"></span> }
00224
00225 al = (<a class="code" href="timer_8h.html#a1">talarm_t</a>*)u_zalloc(<span class="keyword">sizeof</span>(<a class="code" href="timer_8h.html#a1">talarm_t</a>));
00226 dbg_err_if(al == NULL);
00227
00228 al->timer = timer;
00229 al->cb = cb;
00230 al->arg = arg;
00231 al->expire = now + secs;
00232
00233 dbg_err_if(timerm_block_alarms());
00234
00235 <span class="comment">/* insert al ordered by the expire field (smaller first) */</span>
00236 TAILQ_FOREACH(item, &timer->alist, np)
00237 <span class="keywordflow">if</span>(al->expire <= item->expire)
00238 <span class="keywordflow">break</span>;
00239
00240 <span class="keywordflow">if</span>(item)
00241 TAILQ_INSERT_BEFORE(item, al, np);
00242 <span class="keywordflow">else</span>
00243 TAILQ_INSERT_TAIL(&timer->alist, al, np);
00244
00245 <span class="comment">/* set the timer for the earliest alarm */</span>
00246 timerm_set_next();
00247
00248 dbg_err_if(timerm_unblock_alarms());
00249
00250 *pa = al;
00251
00252 <span class="keywordflow">return</span> 0;
00253 err:
00254 dbg(<span class="stringliteral">"[%lu] timerm_add error"</span>, getpid());
00255 <span class="keywordflow">if</span>(timer)
00256 {
00257 (void) timerm_free(timer);
00258 timer = NULL;
00259 }
00260 U_FREE(al);
00261
00262 dbg_err_if(timerm_unblock_alarms());
00263
00264 <span class="keywordflow">return</span> ~0;
00265 }
00266
00267 <span class="keyword">static</span> <span class="keywordtype">int</span> timerm_alarm_pending(<a class="code" href="timer_8h.html#a1">talarm_t</a> *a)
00268 {
00269 <a class="code" href="timer_8h.html#a1">talarm_t</a> *t;
00270
00271 TAILQ_FOREACH(t, &timer->alist,np)
00272 {
00273 <span class="keywordflow">if</span>(t == a)
00274 <span class="keywordflow">return</span> 1; <span class="comment">/* found */</span>
00275 }
00276 <span class="keywordflow">return</span> 0;
00277 }
00278
<a name="l00279"></a><a class="code" href="timer_8h.html#a4">00279</a> <span class="keywordtype">int</span> <a class="code" href="timer_8h.html#a4">timerm_del</a>(<a class="code" href="timer_8h.html#a1">talarm_t</a> *a)
00280 {
00281 dbg_return_if(a == NULL, ~0);
00282
00283 dbg_err_if(timerm_block_alarms());
00284
00285 <span class="comment">/* if not expired remove it from the list */</span>
00286 <span class="keywordflow">if</span>(timerm_alarm_pending(a))
00287 TAILQ_REMOVE(&timer->alist, a, np);
00288
00289 <span class="comment">/* set the timer for the earliest alarm */</span>
00290 timerm_set_next();
00291
00292 dbg_err_if(timerm_unblock_alarms());
00293
00294 U_FREE(a);
00295
00296 <span class="keywordflow">return</span> 0;
00297 err:
00298 dbg_err_if(timerm_unblock_alarms());
00299 <span class="keywordflow">return</span> ~0;
00300 }
</pre></div><hr>
<div>
<div style="text-align:left">
<a href="http://www.koanlogic.com/kl/cont/gb/html/products.html">←Products</a>
</div>
<div style="text-align:center;">
© 2005-2006 - <a href="http://www.koanlogic.com">KoanLogic S.r.l.</a> - All rights reserved
</div>
</div>
</body>
</html>
|