1 /*
2 NETWIB
3 Network library
4 Copyright(c) 1999-2010 Laurent Constantin
5 -----
6
7 Main server : http://www.laurentconstantin.com/
8 Backup server : http://laurentconstantin.free.fr/
9 [my current email address is on the web servers]
10
11 -----
12 This file is part of Netwib.
13
14 Netwib is free software: you can redistribute it and/or modify
15 it under the terms of the GNU General Public License version 3
16 as published by the Free Software Foundation.
17
18 Netwib is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details (http://www.gnu.org/).
22
23 ------------------------------------------------------------------------
24 */
25
26 #include <netwib/inc/maininc.h>
27
28 /*-------------------------------------------------------------*/
29 struct netwib_wait {
30 netwib_wait_event_pf pfuncevent;
31 netwib_ptr infos;
32 netwib_wait_close_pf pfuncclose;
33 };
34
35 /*-------------------------------------------------------------*/
netwib_wait_init(netwib_wait_event_pf pfuncevent,netwib_ptr infos,netwib_wait_close_pf pfuncclose,netwib_wait ** ppwait)36 netwib_err netwib_wait_init(netwib_wait_event_pf pfuncevent,
37 netwib_ptr infos,
38 netwib_wait_close_pf pfuncclose,
39 netwib_wait **ppwait)
40 {
41 netwib_wait *pwait;
42
43 /* allocate needed memory to store pwait */
44 netwib_er(netwib_ptr_malloc(sizeof(netwib_wait), (netwib_ptr*)&pwait));
45 *ppwait = pwait;
46 pwait->pfuncevent = pfuncevent;
47 pwait->infos = infos;
48 pwait->pfuncclose = pfuncclose;
49
50 #if NETWIB_DEBUG_LEAK==1
51 netwib_er(netwib_debug_leak_add_wait(pwait));
52 #endif
53
54 return(NETWIB_ERR_OK);
55 }
56
57 /*-------------------------------------------------------------*/
netwib_wait_close(netwib_wait ** ppwait)58 netwib_err netwib_wait_close(netwib_wait **ppwait)
59 {
60 netwib_wait *pwait;
61
62 /* parameter verification */
63 if (ppwait == NULL) {
64 return(NETWIB_ERR_PANULLPTR);
65 }
66 pwait = *ppwait;
67
68 if (pwait->pfuncclose != NULL) {
69 netwib_er((*pwait->pfuncclose)(pwait->infos));
70 }
71
72 #if NETWIB_DEBUG_LEAK==1
73 netwib_er(netwib_debug_leak_del_wait(*ppwait));
74 #endif
75
76 /* free memory */
77 netwib_er(netwib_ptr_free((netwib_ptr*)ppwait));
78
79 return(NETWIB_ERR_OK);
80 }
81
82 /*-------------------------------------------------------------*/
83 typedef struct {
84 netwib_io *pio;
85 netwib_io_waytype way;
86 } netwib_priv_wait_io;
netwib_priv_wait_event_io(netwib_ptr infos,netwib_consttime * pabstime,netwib_bool * pevent)87 static netwib_err netwib_priv_wait_event_io(netwib_ptr infos,
88 netwib_consttime *pabstime,
89 netwib_bool *pevent)
90 {
91 netwib_priv_wait_io *pwio = (netwib_priv_wait_io *)infos;
92
93 netwib_er(netwib_io_wait(pwio->pio, pwio->way, pabstime, pevent));
94 return(NETWIB_ERR_OK);
95 }
netwib_priv_wait_close_io(netwib_ptr infos)96 static netwib_err netwib_priv_wait_close_io(netwib_ptr infos)
97 {
98 netwib_er(netwib_ptr_free(&infos));
99 return(NETWIB_ERR_OK);
100 }
netwib_wait_init_io(netwib_io * pio,netwib_io_waytype way,netwib_wait ** ppwait)101 netwib_err netwib_wait_init_io(netwib_io *pio,
102 netwib_io_waytype way,
103 netwib_wait **ppwait)
104 {
105 netwib_priv_wait_io *pwio;
106
107 netwib_er(netwib_ptr_malloc(sizeof(netwib_priv_wait_io),
108 (netwib_ptr*)&pwio));
109 pwio->pio = pio;
110 pwio->way = way;
111
112 netwib_er(netwib_wait_init(&netwib_priv_wait_event_io, pwio,
113 &netwib_priv_wait_close_io, ppwait));
114 return(NETWIB_ERR_OK);
115 }
116
117 /*-------------------------------------------------------------*/
118 typedef struct {
119 netwib_thread *pthread;
120 netwib_err *preturnederror;
121 netwib_ptr *pinfosout;
122 } netwib_priv_wait_thread;
netwib_priv_wait_event_thread(netwib_ptr infos,netwib_consttime * pabstime,netwib_bool * pevent)123 static netwib_err netwib_priv_wait_event_thread(netwib_ptr infos,
124 netwib_consttime *pabstime,
125 netwib_bool *pevent)
126 {
127 netwib_priv_wait_thread *pwthread = (netwib_priv_wait_thread *)infos;
128
129 netwib_er(netwib_thread_wait(pwthread->pthread, pabstime, pevent,
130 pwthread->preturnederror, pwthread->pinfosout));
131 return(NETWIB_ERR_OK);
132 }
netwib_priv_wait_close_thread(netwib_ptr infos)133 static netwib_err netwib_priv_wait_close_thread(netwib_ptr infos)
134 {
135 netwib_er(netwib_ptr_free(&infos));
136 return(NETWIB_ERR_OK);
137 }
netwib_wait_init_thread_end(netwib_thread * pthread,netwib_err * preturnederror,netwib_ptr * pinfosout,netwib_wait ** ppwait)138 netwib_err netwib_wait_init_thread_end(netwib_thread *pthread,
139 netwib_err *preturnederror,
140 netwib_ptr *pinfosout,
141 netwib_wait **ppwait)
142 {
143 netwib_priv_wait_thread *pwthread;
144
145 netwib_er(netwib_ptr_malloc(sizeof(netwib_priv_wait_thread),
146 (netwib_ptr*)&pwthread));
147 pwthread->pthread = pthread;
148 pwthread->preturnederror = preturnederror;
149 pwthread->pinfosout = pinfosout;
150
151 netwib_er(netwib_wait_init(&netwib_priv_wait_event_thread, pwthread,
152 &netwib_priv_wait_close_thread, ppwait));
153 return(NETWIB_ERR_OK);
154 }
155
156 /*-------------------------------------------------------------*/
157 typedef struct {
158 netwib_thread_cond *pcond;
159 netwib_uint32 *pvalue;
160 } netwib_priv_wait_thread_cond;
netwib_priv_wait_event_thread_cond(netwib_ptr infos,netwib_consttime * pabstime,netwib_bool * pevent)161 static netwib_err netwib_priv_wait_event_thread_cond(netwib_ptr infos,
162 netwib_consttime *pabstime,
163 netwib_bool *pevent)
164 {
165 netwib_priv_wait_thread_cond *pwthread = (netwib_priv_wait_thread_cond *)infos;
166
167 netwib_er(netwib_thread_cond_wait(pwthread->pcond, pabstime, pevent,
168 pwthread->pvalue));
169 return(NETWIB_ERR_OK);
170 }
netwib_priv_wait_close_thread_cond(netwib_ptr infos)171 static netwib_err netwib_priv_wait_close_thread_cond(netwib_ptr infos)
172 {
173 netwib_er(netwib_ptr_free(&infos));
174 return(NETWIB_ERR_OK);
175 }
netwib_wait_init_thread_cond(netwib_thread_cond * pcond,netwib_uint32 * pvalue,netwib_wait ** ppwait)176 netwib_err netwib_wait_init_thread_cond(netwib_thread_cond *pcond,
177 netwib_uint32 *pvalue,
178 netwib_wait **ppwait)
179 {
180 netwib_priv_wait_thread_cond *pwthread;
181
182 netwib_er(netwib_ptr_malloc(sizeof(netwib_priv_wait_thread_cond),
183 (netwib_ptr*)&pwthread));
184 pwthread->pcond = pcond;
185 pwthread->pvalue = pvalue;
186
187 netwib_er(netwib_wait_init(&netwib_priv_wait_event_thread_cond, pwthread,
188 &netwib_priv_wait_close_thread_cond, ppwait));
189 return(NETWIB_ERR_OK);
190 }
191
192 /*-------------------------------------------------------------*/
netwib_wait_wait1(netwib_wait * pwait,netwib_consttime * pabstime,netwib_bool * pevent)193 netwib_err netwib_wait_wait1(netwib_wait *pwait,
194 netwib_consttime *pabstime,
195 netwib_bool *pevent)
196 {
197 /* parameters verification */
198 if (pwait == NULL) {
199 return(NETWIB_ERR_PANULLPTR);
200 }
201 #if NETWIB_DEBUG_LEAK==1
202 netwib_er(netwib_debug_leak_valid_wait(pwait));
203 #endif
204
205 netwib_er((*pwait->pfuncevent)(pwait->infos, pabstime, pevent));
206
207 return(NETWIB_ERR_OK);
208 }
209
210 /*-------------------------------------------------------------*/
netwib_priv_wait_wait5(netwib_wait * pwait1,netwib_wait * pwait2,netwib_wait * pwait3,netwib_wait * pwait4,netwib_wait * pwait5,netwib_bool * pevent,netwib_bool * pevent1,netwib_bool * pevent2,netwib_bool * pevent3,netwib_bool * pevent4,netwib_bool * pevent5)211 static netwib_err netwib_priv_wait_wait5(netwib_wait *pwait1,
212 netwib_wait *pwait2,
213 netwib_wait *pwait3,
214 netwib_wait *pwait4,
215 netwib_wait *pwait5,
216 netwib_bool *pevent,
217 netwib_bool *pevent1,
218 netwib_bool *pevent2,
219 netwib_bool *pevent3,
220 netwib_bool *pevent4,
221 netwib_bool *pevent5)
222 {
223 netwib_bool event;
224
225 *pevent = NETWIB_FALSE;
226
227 if (pwait1 != NULL) {
228 netwib_er((*pwait1->pfuncevent)(pwait1->infos, NETWIB_TIME_ZERO, &event));
229 if (pevent1 != NULL) *pevent1 = event;
230 if (event) *pevent = NETWIB_TRUE;
231 }
232 if (pwait2 != NULL) {
233 netwib_er((*pwait2->pfuncevent)(pwait2->infos, NETWIB_TIME_ZERO, &event));
234 if (pevent2 != NULL) *pevent2 = event;
235 if (event) *pevent = NETWIB_TRUE;
236 }
237 if (pwait3 != NULL) {
238 netwib_er((*pwait3->pfuncevent)(pwait3->infos, NETWIB_TIME_ZERO, &event));
239 if (pevent3 != NULL) *pevent3 = event;
240 if (event) *pevent = NETWIB_TRUE;
241 }
242 if (pwait4 != NULL) {
243 netwib_er((*pwait4->pfuncevent)(pwait4->infos, NETWIB_TIME_ZERO, &event));
244 if (pevent4 != NULL) *pevent4 = event;
245 if (event) *pevent = NETWIB_TRUE;
246 }
247 if (pwait5 != NULL) {
248 netwib_er((*pwait5->pfuncevent)(pwait5->infos, NETWIB_TIME_ZERO, &event));
249 if (pevent5 != NULL) *pevent5 = event;
250 if (event) *pevent = NETWIB_TRUE;
251 }
252
253 return(NETWIB_ERR_OK);
254 }
255
256 /*-------------------------------------------------------------*/
netwib_wait_wait5(netwib_wait * pwait1,netwib_wait * pwait2,netwib_wait * pwait3,netwib_wait * pwait4,netwib_wait * pwait5,netwib_consttime * pabstime,netwib_bool * pevent1,netwib_bool * pevent2,netwib_bool * pevent3,netwib_bool * pevent4,netwib_bool * pevent5)257 netwib_err netwib_wait_wait5(netwib_wait *pwait1,
258 netwib_wait *pwait2,
259 netwib_wait *pwait3,
260 netwib_wait *pwait4,
261 netwib_wait *pwait5,
262 netwib_consttime *pabstime,
263 netwib_bool *pevent1,
264 netwib_bool *pevent2,
265 netwib_bool *pevent3,
266 netwib_bool *pevent4,
267 netwib_bool *pevent5)
268 {
269 netwib_uint32 numcalls;
270 netwib_bool event, elapsed;
271
272 #if NETWIB_DEBUG_LEAK==1
273 if (pwait1 != NULL) {
274 netwib_er(netwib_debug_leak_valid_wait(pwait1));
275 }
276 if (pwait2 != NULL) {
277 netwib_er(netwib_debug_leak_valid_wait(pwait2));
278 }
279 if (pwait3 != NULL) {
280 netwib_er(netwib_debug_leak_valid_wait(pwait3));
281 }
282 if (pwait4 != NULL) {
283 netwib_er(netwib_debug_leak_valid_wait(pwait4));
284 }
285 if (pwait5 != NULL) {
286 netwib_er(netwib_debug_leak_valid_wait(pwait5));
287 }
288 #endif
289
290 if (pabstime == NETWIB_TIME_ZERO) {
291 netwib_er(netwib_priv_wait_wait5(pwait1, pwait2, pwait3, pwait4, pwait5,
292 &event,
293 pevent1, pevent2, pevent3, pevent4,
294 pevent5));
295 return(NETWIB_ERR_OK);
296 }
297
298 if (pabstime == NETWIB_TIME_INFINITE) {
299 numcalls = 0;
300 while (NETWIB_TRUE) {
301 netwib_er(netwib_priv_wait_wait5(pwait1, pwait2, pwait3, pwait4, pwait5,
302 &event,
303 pevent1, pevent2, pevent3, pevent4,
304 pevent5));
305 if (event) {
306 return(NETWIB_ERR_OK);
307 }
308 /* small pause */
309 netwib_er(netwib_priv_pause2(&numcalls));
310 }
311 }
312
313 numcalls = 0;
314 while (NETWIB_TRUE) {
315 /* check time */
316 netwib_er(netwib_time_iselapsed(pabstime, &elapsed));
317 if (elapsed) {
318 if (pevent1 != NULL) *pevent1 = NETWIB_FALSE;
319 if (pevent2 != NULL) *pevent2 = NETWIB_FALSE;
320 if (pevent3 != NULL) *pevent3 = NETWIB_FALSE;
321 if (pevent4 != NULL) *pevent4 = NETWIB_FALSE;
322 if (pevent5 != NULL) *pevent5 = NETWIB_FALSE;
323 break;
324 }
325 /* wait */
326 netwib_er(netwib_priv_wait_wait5(pwait1, pwait2, pwait3, pwait4, pwait5,
327 &event,
328 pevent1, pevent2, pevent3, pevent4,
329 pevent5));
330 if (event) {
331 break;
332 }
333 /* small pause */
334 netwib_er(netwib_priv_pause2(&numcalls));
335 }
336
337 return(NETWIB_ERR_OK);
338 }
339