2 * Event loop based on Windows events and WaitForMultipleObjects
3 * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
26 eloop_sock_handler handler
;
33 eloop_event_handler handler
;
37 struct eloop_timeout
{
41 eloop_timeout_handler handler
;
42 struct eloop_timeout
*next
;
48 eloop_signal_handler handler
;
57 struct eloop_sock
*readers
;
60 struct eloop_event
*events
;
62 struct eloop_timeout
*timeout
;
65 struct eloop_signal
*signals
;
67 int pending_terminate
;
70 int reader_table_changed
;
72 struct eloop_signal term_signal
;
79 static struct eloop_data eloop
;
82 int eloop_init(void *user_data
)
84 os_memset(&eloop
, 0, sizeof(eloop
));
85 eloop
.user_data
= user_data
;
86 eloop
.num_handles
= 1;
87 eloop
.handles
= os_malloc(eloop
.num_handles
*
88 sizeof(eloop
.handles
[0]));
89 if (eloop
.handles
== NULL
)
92 eloop
.term_event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
93 if (eloop
.term_event
== NULL
) {
94 printf("CreateEvent() failed: %d\n",
95 (int) GetLastError());
96 os_free(eloop
.handles
);
104 static int eloop_prepare_handles(void)
108 if (eloop
.num_handles
> eloop
.reader_count
+ eloop
.event_count
+ 8)
110 n
= os_realloc(eloop
.handles
,
111 eloop
.num_handles
* 2 * sizeof(eloop
.handles
[0]));
115 eloop
.num_handles
*= 2;
120 int eloop_register_read_sock(int sock
, eloop_sock_handler handler
,
121 void *eloop_data
, void *user_data
)
124 struct eloop_sock
*tmp
;
126 if (eloop_prepare_handles())
129 event
= WSACreateEvent();
130 if (event
== WSA_INVALID_EVENT
) {
131 printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
135 if (WSAEventSelect(sock
, event
, FD_READ
)) {
136 printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
137 WSACloseEvent(event
);
140 tmp
= os_realloc(eloop
.readers
,
141 (eloop
.reader_count
+ 1) * sizeof(struct eloop_sock
));
143 WSAEventSelect(sock
, event
, 0);
144 WSACloseEvent(event
);
148 tmp
[eloop
.reader_count
].sock
= sock
;
149 tmp
[eloop
.reader_count
].eloop_data
= eloop_data
;
150 tmp
[eloop
.reader_count
].user_data
= user_data
;
151 tmp
[eloop
.reader_count
].handler
= handler
;
152 tmp
[eloop
.reader_count
].event
= event
;
153 eloop
.reader_count
++;
155 if (sock
> eloop
.max_sock
)
156 eloop
.max_sock
= sock
;
157 eloop
.reader_table_changed
= 1;
163 void eloop_unregister_read_sock(int sock
)
167 if (eloop
.readers
== NULL
|| eloop
.reader_count
== 0)
170 for (i
= 0; i
< eloop
.reader_count
; i
++) {
171 if (eloop
.readers
[i
].sock
== sock
)
174 if (i
== eloop
.reader_count
)
177 WSAEventSelect(eloop
.readers
[i
].sock
, eloop
.readers
[i
].event
, 0);
178 WSACloseEvent(eloop
.readers
[i
].event
);
180 if (i
!= eloop
.reader_count
- 1) {
181 os_memmove(&eloop
.readers
[i
], &eloop
.readers
[i
+ 1],
182 (eloop
.reader_count
- i
- 1) *
183 sizeof(struct eloop_sock
));
185 eloop
.reader_count
--;
186 eloop
.reader_table_changed
= 1;
190 int eloop_register_event(void *event
, size_t event_size
,
191 eloop_event_handler handler
,
192 void *eloop_data
, void *user_data
)
194 struct eloop_event
*tmp
;
197 if (event_size
!= sizeof(HANDLE
) || h
== INVALID_HANDLE_VALUE
)
200 if (eloop_prepare_handles())
203 tmp
= os_realloc(eloop
.events
,
204 (eloop
.event_count
+ 1) * sizeof(struct eloop_event
));
208 tmp
[eloop
.event_count
].eloop_data
= eloop_data
;
209 tmp
[eloop
.event_count
].user_data
= user_data
;
210 tmp
[eloop
.event_count
].handler
= handler
;
211 tmp
[eloop
.event_count
].event
= h
;
219 void eloop_unregister_event(void *event
, size_t event_size
)
224 if (eloop
.events
== NULL
|| eloop
.event_count
== 0 ||
225 event_size
!= sizeof(HANDLE
))
228 for (i
= 0; i
< eloop
.event_count
; i
++) {
229 if (eloop
.events
[i
].event
== h
)
232 if (i
== eloop
.event_count
)
235 if (i
!= eloop
.event_count
- 1) {
236 os_memmove(&eloop
.events
[i
], &eloop
.events
[i
+ 1],
237 (eloop
.event_count
- i
- 1) *
238 sizeof(struct eloop_event
));
244 int eloop_register_timeout(unsigned int secs
, unsigned int usecs
,
245 eloop_timeout_handler handler
,
246 void *eloop_data
, void *user_data
)
248 struct eloop_timeout
*timeout
, *tmp
, *prev
;
250 timeout
= os_malloc(sizeof(*timeout
));
253 os_get_time(&timeout
->time
);
254 timeout
->time
.sec
+= secs
;
255 timeout
->time
.usec
+= usecs
;
256 while (timeout
->time
.usec
>= 1000000) {
258 timeout
->time
.usec
-= 1000000;
260 timeout
->eloop_data
= eloop_data
;
261 timeout
->user_data
= user_data
;
262 timeout
->handler
= handler
;
263 timeout
->next
= NULL
;
265 if (eloop
.timeout
== NULL
) {
266 eloop
.timeout
= timeout
;
272 while (tmp
!= NULL
) {
273 if (os_time_before(&timeout
->time
, &tmp
->time
))
280 timeout
->next
= eloop
.timeout
;
281 eloop
.timeout
= timeout
;
283 timeout
->next
= prev
->next
;
284 prev
->next
= timeout
;
291 int eloop_cancel_timeout(eloop_timeout_handler handler
,
292 void *eloop_data
, void *user_data
)
294 struct eloop_timeout
*timeout
, *prev
, *next
;
298 timeout
= eloop
.timeout
;
299 while (timeout
!= NULL
) {
300 next
= timeout
->next
;
302 if (timeout
->handler
== handler
&&
303 (timeout
->eloop_data
== eloop_data
||
304 eloop_data
== ELOOP_ALL_CTX
) &&
305 (timeout
->user_data
== user_data
||
306 user_data
== ELOOP_ALL_CTX
)) {
308 eloop
.timeout
= next
;
323 int eloop_is_timeout_registered(eloop_timeout_handler handler
,
324 void *eloop_data
, void *user_data
)
326 struct eloop_timeout
*tmp
;
329 while (tmp
!= NULL
) {
330 if (tmp
->handler
== handler
&&
331 tmp
->eloop_data
== eloop_data
&&
332 tmp
->user_data
== user_data
)
342 /* TODO: replace with suitable signal handler */
344 static void eloop_handle_signal(int sig
)
349 for (i
= 0; i
< eloop
.signal_count
; i
++) {
350 if (eloop
.signals
[i
].sig
== sig
) {
351 eloop
.signals
[i
].signaled
++;
359 static void eloop_process_pending_signals(void)
363 if (eloop
.signaled
== 0)
367 if (eloop
.pending_terminate
) {
368 eloop
.pending_terminate
= 0;
371 for (i
= 0; i
< eloop
.signal_count
; i
++) {
372 if (eloop
.signals
[i
].signaled
) {
373 eloop
.signals
[i
].signaled
= 0;
374 eloop
.signals
[i
].handler(eloop
.signals
[i
].sig
,
376 eloop
.signals
[i
].user_data
);
380 if (eloop
.term_signal
.signaled
) {
381 eloop
.term_signal
.signaled
= 0;
382 eloop
.term_signal
.handler(eloop
.term_signal
.sig
,
384 eloop
.term_signal
.user_data
);
389 int eloop_register_signal(int sig
, eloop_signal_handler handler
,
392 struct eloop_signal
*tmp
;
394 tmp
= os_realloc(eloop
.signals
,
395 (eloop
.signal_count
+ 1) *
396 sizeof(struct eloop_signal
));
400 tmp
[eloop
.signal_count
].sig
= sig
;
401 tmp
[eloop
.signal_count
].user_data
= user_data
;
402 tmp
[eloop
.signal_count
].handler
= handler
;
403 tmp
[eloop
.signal_count
].signaled
= 0;
404 eloop
.signal_count
++;
407 /* TODO: register signal handler */
414 static BOOL
eloop_handle_console_ctrl(DWORD type
)
418 case CTRL_BREAK_EVENT
:
420 eloop
.term_signal
.signaled
++;
421 SetEvent(eloop
.term_event
);
427 #endif /* _WIN32_WCE */
430 int eloop_register_signal_terminate(eloop_signal_handler handler
,
434 if (SetConsoleCtrlHandler((PHANDLER_ROUTINE
) eloop_handle_console_ctrl
,
436 printf("SetConsoleCtrlHandler() failed: %d\n",
437 (int) GetLastError());
440 #endif /* _WIN32_WCE */
442 eloop
.term_signal
.handler
= handler
;
443 eloop
.term_signal
.user_data
= user_data
;
449 int eloop_register_signal_reconfig(eloop_signal_handler handler
,
459 struct os_time tv
, now
;
460 DWORD count
, ret
, timeout
, err
;
463 while (!eloop
.terminate
&&
464 (eloop
.timeout
|| eloop
.reader_count
> 0 ||
465 eloop
.event_count
> 0)) {
468 if (os_time_before(&now
, &eloop
.timeout
->time
))
469 os_time_sub(&eloop
.timeout
->time
, &now
, &tv
);
471 tv
.sec
= tv
.usec
= 0;
475 for (i
= 0; i
< eloop
.event_count
; i
++)
476 eloop
.handles
[count
++] = eloop
.events
[i
].event
;
478 for (i
= 0; i
< eloop
.reader_count
; i
++)
479 eloop
.handles
[count
++] = eloop
.readers
[i
].event
;
481 if (eloop
.term_event
)
482 eloop
.handles
[count
++] = eloop
.term_event
;
485 timeout
= tv
.sec
* 1000 + tv
.usec
/ 1000;
489 if (count
> MAXIMUM_WAIT_OBJECTS
) {
490 printf("WaitForMultipleObjects: Too many events: "
491 "%d > %d (ignoring extra events)\n",
492 (int) count
, MAXIMUM_WAIT_OBJECTS
);
493 count
= MAXIMUM_WAIT_OBJECTS
;
496 ret
= WaitForMultipleObjects(count
, eloop
.handles
, FALSE
,
498 #else /* _WIN32_WCE */
499 ret
= WaitForMultipleObjectsEx(count
, eloop
.handles
, FALSE
,
501 #endif /* _WIN32_WCE */
502 err
= GetLastError();
504 eloop_process_pending_signals();
506 /* check if some registered timeouts have occurred */
508 struct eloop_timeout
*tmp
;
511 if (!os_time_before(&now
, &eloop
.timeout
->time
)) {
513 eloop
.timeout
= eloop
.timeout
->next
;
514 tmp
->handler(tmp
->eloop_data
,
521 if (ret
== WAIT_FAILED
) {
522 printf("WaitForMultipleObjects(count=%d) failed: %d\n",
523 (int) count
, (int) err
);
529 if (ret
== WAIT_IO_COMPLETION
)
531 #endif /* _WIN32_WCE */
533 if (ret
== WAIT_TIMEOUT
)
536 while (ret
>= WAIT_OBJECT_0
&&
537 ret
< WAIT_OBJECT_0
+ eloop
.event_count
) {
538 eloop
.events
[ret
].handler(
539 eloop
.events
[ret
].eloop_data
,
540 eloop
.events
[ret
].user_data
);
541 ret
= WaitForMultipleObjects(eloop
.event_count
,
542 eloop
.handles
, FALSE
, 0);
545 eloop
.reader_table_changed
= 0;
546 for (i
= 0; i
< eloop
.reader_count
; i
++) {
547 WSANETWORKEVENTS events
;
548 if (WSAEnumNetworkEvents(eloop
.readers
[i
].sock
,
549 eloop
.readers
[i
].event
,
551 (events
.lNetworkEvents
& FD_READ
)) {
552 eloop
.readers
[i
].handler(
553 eloop
.readers
[i
].sock
,
554 eloop
.readers
[i
].eloop_data
,
555 eloop
.readers
[i
].user_data
);
556 if (eloop
.reader_table_changed
)
564 void eloop_terminate(void)
567 SetEvent(eloop
.term_event
);
571 void eloop_destroy(void)
573 struct eloop_timeout
*timeout
, *prev
;
575 timeout
= eloop
.timeout
;
576 while (timeout
!= NULL
) {
578 timeout
= timeout
->next
;
581 os_free(eloop
.readers
);
582 os_free(eloop
.signals
);
583 if (eloop
.term_event
)
584 CloseHandle(eloop
.term_event
);
585 os_free(eloop
.handles
);
586 eloop
.handles
= NULL
;
587 os_free(eloop
.events
);
592 int eloop_terminated(void)
594 return eloop
.terminate
;
598 void eloop_wait_for_read_sock(int sock
)
602 event
= WSACreateEvent();
603 if (event
== WSA_INVALID_EVENT
) {
604 printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
608 if (WSAEventSelect(sock
, event
, FD_READ
)) {
609 printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
610 WSACloseEvent(event
);
614 WaitForSingleObject(event
, INFINITE
);
615 WSAEventSelect(sock
, event
, 0);
616 WSACloseEvent(event
);
620 void * eloop_get_user_data(void)
622 return eloop
.user_data
;