File: timer_8c-source.html

package info (click to toggle)
klone 1.1.1.dfsg1-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 6,480 kB
  • ctags: 4,238
  • sloc: ansic: 16,288; makefile: 384; sh: 351
file content (321 lines) | stat: -rw-r--r-- 16,081 bytes parent folder | download
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&nbsp;Page</a> | <a class="qindex" href="modules.html">Modules</a> | <a class="qindex" href="annotated.html">Data&nbsp;Structures</a> | <a class="qindex" href="dirs.html">Directories</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Data&nbsp;Fields</a> | <a class="qindex" href="globals.html">Globals</a></div>
<div class="nav">
<a class="el" href="dir_000000.html">src</a>&nbsp;/&nbsp;<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. &lt;http://www.koanlogic.com&gt;</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 &lt;time.h&gt;</span>
00013 <span class="preprocessor">#include &lt;unistd.h&gt;</span>
00014 <span class="preprocessor">#include &lt;signal.h&gt;</span>
00015 <span class="preprocessor">#include &lt;<a class="code" href="timer_8h.html">klone/timer.h</a>&gt;</span>
00016 <span class="preprocessor">#include &lt;<a class="code" href="utils_8h.html">klone/utils.h</a>&gt;</span>
00017 <span class="preprocessor">#include &lt;u/libu.h&gt;</span>
00018 
00019 <span class="preprocessor">#ifdef OS_WIN</span>
00020 <span class="preprocessor"></span><span class="preprocessor">#include &lt;windows.h&gt;</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 &amp; 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 &gt; 0)
00059         timer-&gt;next = time(0) + timeout;
00060     <span class="keywordflow">else</span>
00061         timer-&gt;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(&amp;timer-&gt;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-&gt;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(&amp;timer-&gt;alist);
00093         dbg_err_if(al == NULL);
00094 
00095         expire = al-&gt;expire;
00096 
00097         TAILQ_REMOVE(&amp;timer-&gt;alist, al, np);
00098 
00099         <span class="comment">/* call the callback function */</span>
00100         al-&gt;cb(al, al-&gt;arg);
00101 
00102         <span class="comment">/* handle alarms with the same expiration date */</span>
00103         next = TAILQ_FIRST(&amp;timer-&gt;alist);
00104         <span class="keywordflow">if</span>(next &amp;&amp; next-&gt;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(&amp;timer-&gt;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(&amp;timer-&gt;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(&amp;timer-&gt;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(&amp;t-&gt;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-&gt;next == NULL)
00171             <span class="keywordflow">continue</span>;
00172 
00173         <span class="keywordflow">if</span>((timer-&gt;next - time(0)) &lt;= 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(&amp;t-&gt;alist);
00191 
00192 <span class="preprocessor">#ifdef OS_WIN</span>
00193 <span class="preprocessor"></span>    InitializeCriticalSection(&amp;t-&gt;cs);
00194 
00195     dbg_err_if((t-&gt;hthread = CreateThread(NULL, 0, thread_func, NULL, 0, 
00196         &amp;t-&gt;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(&amp;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-&gt;timer = timer;
00229     al-&gt;cb = cb;
00230     al-&gt;arg = arg;
00231     al-&gt;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, &amp;timer-&gt;alist, np)
00237         <span class="keywordflow">if</span>(al-&gt;expire &lt;= item-&gt;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(&amp;timer-&gt;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, &amp;timer-&gt;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(&amp;timer-&gt;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">&larr;Products</a>
  </div>
  <div style="text-align:center;">
    &copy; 2005-2006 - <a href="http://www.koanlogic.com">KoanLogic S.r.l.</a> - All rights reserved
  </div>
</div>

</body>
</html>