diff options
Diffstat (limited to 'libraries/ecore/src/lib/ecore/ecore_main.c')
-rw-r--r-- | libraries/ecore/src/lib/ecore/ecore_main.c | 1958 |
1 files changed, 0 insertions, 1958 deletions
diff --git a/libraries/ecore/src/lib/ecore/ecore_main.c b/libraries/ecore/src/lib/ecore/ecore_main.c deleted file mode 100644 index 587c83b..0000000 --- a/libraries/ecore/src/lib/ecore/ecore_main.c +++ /dev/null | |||
@@ -1,1958 +0,0 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif | ||
4 | |||
5 | #ifdef _WIN32 | ||
6 | # define WIN32_LEAN_AND_MEAN | ||
7 | # include <winsock2.h> | ||
8 | # undef WIN32_LEAN_AND_MEAN | ||
9 | # ifndef USER_TIMER_MINIMUM | ||
10 | # define USER_TIMER_MINIMUM 0x0a | ||
11 | # endif | ||
12 | #endif | ||
13 | |||
14 | #ifdef __SUNPRO_C | ||
15 | # include <ieeefp.h> | ||
16 | # include <string.h> | ||
17 | #endif | ||
18 | |||
19 | #include <stdlib.h> | ||
20 | #include <stdio.h> | ||
21 | #include <math.h> | ||
22 | #include <sys/types.h> | ||
23 | #include <errno.h> | ||
24 | #include <fcntl.h> | ||
25 | |||
26 | #ifndef _MSC_VER | ||
27 | # include <sys/time.h> | ||
28 | # include <unistd.h> | ||
29 | #else | ||
30 | # include <float.h> | ||
31 | #endif | ||
32 | |||
33 | #ifdef HAVE_ISFINITE | ||
34 | # define ECORE_FINITE(t) isfinite(t) | ||
35 | #else | ||
36 | # ifdef _MSC_VER | ||
37 | # define ECORE_FINITE(t) _finite(t) | ||
38 | # else | ||
39 | # define ECORE_FINITE(t) finite(t) | ||
40 | # endif | ||
41 | #endif | ||
42 | |||
43 | //#define FIX_HZ 1 | ||
44 | |||
45 | #ifdef FIX_HZ | ||
46 | # ifndef _MSC_VER | ||
47 | # include <sys/param.h> | ||
48 | # endif | ||
49 | # ifndef HZ | ||
50 | # define HZ 100 | ||
51 | # endif | ||
52 | #endif | ||
53 | |||
54 | #ifdef HAVE_EVIL | ||
55 | # include <Evil.h> | ||
56 | #endif | ||
57 | |||
58 | #include "Ecore.h" | ||
59 | #include "ecore_private.h" | ||
60 | |||
61 | #ifdef HAVE_SYS_EPOLL_H | ||
62 | # define HAVE_EPOLL 1 | ||
63 | # include <sys/epoll.h> | ||
64 | #else | ||
65 | |||
66 | # define HAVE_EPOLL 0 | ||
67 | # define EPOLLIN 1 | ||
68 | # define EPOLLOUT 2 | ||
69 | # define EPOLLERR 8 | ||
70 | |||
71 | #define EPOLL_CTL_ADD 1 | ||
72 | #define EPOLL_CTL_DEL 2 | ||
73 | #define EPOLL_CTL_MOD 3 | ||
74 | |||
75 | typedef union epoll_data { | ||
76 | void *ptr; | ||
77 | int fd; | ||
78 | uint32_t u32; | ||
79 | uint64_t u64; | ||
80 | } epoll_data_t; | ||
81 | |||
82 | struct epoll_event | ||
83 | { | ||
84 | uint32_t events; | ||
85 | epoll_data_t data; | ||
86 | }; | ||
87 | |||
88 | static inline int | ||
89 | epoll_create(int size __UNUSED__) | ||
90 | { | ||
91 | return -1; | ||
92 | } | ||
93 | |||
94 | static inline int | ||
95 | epoll_wait(int epfd __UNUSED__, | ||
96 | struct epoll_event *events __UNUSED__, | ||
97 | int maxevents __UNUSED__, | ||
98 | int timeout __UNUSED__) | ||
99 | { | ||
100 | return -1; | ||
101 | } | ||
102 | |||
103 | static inline int | ||
104 | epoll_ctl(int epfd __UNUSED__, | ||
105 | int op __UNUSED__, | ||
106 | int fd __UNUSED__, | ||
107 | struct epoll_event *event __UNUSED__) | ||
108 | { | ||
109 | return -1; | ||
110 | } | ||
111 | |||
112 | #endif | ||
113 | |||
114 | #ifdef HAVE_SYS_TIMERFD_H | ||
115 | #include <sys/timerfd.h> | ||
116 | #else | ||
117 | /* fallback code if we don't have real timerfd - reduces number of ifdefs */ | ||
118 | #ifndef CLOCK_MONOTONIC | ||
119 | #define CLOCK_MONOTONIC 0 /* bogus value */ | ||
120 | #endif | ||
121 | #ifndef TFD_NONBLOCK | ||
122 | #define TFD_NONBLOCK 0 /* bogus value */ | ||
123 | #endif | ||
124 | static inline int | ||
125 | timerfd_create(int clockid __UNUSED__, | ||
126 | int flags __UNUSED__) | ||
127 | { | ||
128 | return -1; | ||
129 | } | ||
130 | |||
131 | static inline int | ||
132 | timerfd_settime(int fd __UNUSED__, | ||
133 | int flags __UNUSED__, | ||
134 | const struct itimerspec *new_value __UNUSED__, | ||
135 | struct itimerspec *old_value __UNUSED__) | ||
136 | { | ||
137 | return -1; | ||
138 | } | ||
139 | |||
140 | #endif /* HAVE_SYS_TIMERFD_H */ | ||
141 | |||
142 | #ifdef USE_G_MAIN_LOOP | ||
143 | # include <glib.h> | ||
144 | #endif | ||
145 | |||
146 | #define NS_PER_SEC (1000.0 * 1000.0 * 1000.0) | ||
147 | |||
148 | struct _Ecore_Fd_Handler | ||
149 | { | ||
150 | EINA_INLIST; | ||
151 | ECORE_MAGIC; | ||
152 | Ecore_Fd_Handler *next_ready; | ||
153 | int fd; | ||
154 | Ecore_Fd_Handler_Flags flags; | ||
155 | Ecore_Fd_Cb func; | ||
156 | void *data; | ||
157 | Ecore_Fd_Cb buf_func; | ||
158 | void *buf_data; | ||
159 | Ecore_Fd_Prep_Cb prep_func; | ||
160 | void *prep_data; | ||
161 | int references; | ||
162 | Eina_Bool read_active : 1; | ||
163 | Eina_Bool write_active : 1; | ||
164 | Eina_Bool error_active : 1; | ||
165 | Eina_Bool delete_me : 1; | ||
166 | #if defined(USE_G_MAIN_LOOP) | ||
167 | GPollFD gfd; | ||
168 | #endif | ||
169 | }; | ||
170 | GENERIC_ALLOC_SIZE_DECLARE(Ecore_Fd_Handler); | ||
171 | |||
172 | #ifdef _WIN32 | ||
173 | struct _Ecore_Win32_Handler | ||
174 | { | ||
175 | EINA_INLIST; | ||
176 | ECORE_MAGIC; | ||
177 | HANDLE h; | ||
178 | Ecore_Win32_Handle_Cb func; | ||
179 | void *data; | ||
180 | int references; | ||
181 | Eina_Bool delete_me : 1; | ||
182 | }; | ||
183 | GENERIC_ALLOC_SIZE_DECLARE(Ecore_Win32_Handler); | ||
184 | #endif | ||
185 | |||
186 | #ifndef USE_G_MAIN_LOOP | ||
187 | static int _ecore_main_select(double timeout); | ||
188 | #endif | ||
189 | static void _ecore_main_prepare_handlers(void); | ||
190 | static void _ecore_main_fd_handlers_cleanup(void); | ||
191 | #ifndef _WIN32 | ||
192 | # ifndef USE_G_MAIN_LOOP | ||
193 | static void _ecore_main_fd_handlers_bads_rem(void); | ||
194 | # endif | ||
195 | #endif | ||
196 | static void _ecore_main_fd_handlers_call(void); | ||
197 | static int _ecore_main_fd_handlers_buf_call(void); | ||
198 | #ifndef USE_G_MAIN_LOOP | ||
199 | static void _ecore_main_loop_iterate_internal(int once_only); | ||
200 | #endif | ||
201 | |||
202 | #ifdef _WIN32 | ||
203 | static int _ecore_main_win32_select(int nfds, | ||
204 | fd_set *readfds, | ||
205 | fd_set *writefds, | ||
206 | fd_set *exceptfds, | ||
207 | struct timeval *timeout); | ||
208 | static void _ecore_main_win32_handlers_cleanup(void); | ||
209 | #endif | ||
210 | |||
211 | static int in_main_loop = 0; | ||
212 | static int do_quit = 0; | ||
213 | static Ecore_Fd_Handler *fd_handlers = NULL; | ||
214 | static Ecore_Fd_Handler *fd_handler_current = NULL; | ||
215 | static Eina_List *fd_handlers_with_prep = NULL; | ||
216 | static Eina_List *fd_handlers_with_buffer = NULL; | ||
217 | static Eina_List *fd_handlers_to_delete = NULL; | ||
218 | |||
219 | /* single linked list of ready fdhs, terminated by loop to self */ | ||
220 | static Ecore_Fd_Handler *fd_handlers_to_call; | ||
221 | static Ecore_Fd_Handler *fd_handlers_to_call_current; | ||
222 | |||
223 | #ifdef _WIN32 | ||
224 | static Ecore_Win32_Handler *win32_handlers = NULL; | ||
225 | static Ecore_Win32_Handler *win32_handler_current = NULL; | ||
226 | static Eina_Bool win32_handlers_delete_me = EINA_FALSE; | ||
227 | #endif | ||
228 | |||
229 | #ifdef _WIN32 | ||
230 | Ecore_Select_Function main_loop_select = _ecore_main_win32_select; | ||
231 | #else | ||
232 | # if !defined EXOTIC_NO_SELECT | ||
233 | # ifdef HAVE_SYS_SELECT_H | ||
234 | # include <sys/select.h> | ||
235 | # endif | ||
236 | Ecore_Select_Function main_loop_select = select; | ||
237 | # else | ||
238 | Ecore_Select_Function main_loop_select = NULL; | ||
239 | # endif | ||
240 | #endif | ||
241 | |||
242 | #ifndef USE_G_MAIN_LOOP | ||
243 | static double t1 = 0.0; | ||
244 | static double t2 = 0.0; | ||
245 | #endif | ||
246 | |||
247 | static int timer_fd = -1; | ||
248 | static int epoll_fd = -1; | ||
249 | static pid_t epoll_pid; | ||
250 | |||
251 | #ifdef USE_G_MAIN_LOOP | ||
252 | static GPollFD ecore_epoll_fd; | ||
253 | static GPollFD ecore_timer_fd; | ||
254 | static GSource *ecore_glib_source; | ||
255 | static guint ecore_glib_source_id; | ||
256 | static GMainLoop *ecore_main_loop; | ||
257 | static gboolean ecore_idling; | ||
258 | static gboolean _ecore_glib_idle_enterer_called; | ||
259 | static gboolean ecore_fds_ready; | ||
260 | #endif | ||
261 | |||
262 | static inline void | ||
263 | _ecore_fd_valid(void) | ||
264 | { | ||
265 | if (HAVE_EPOLL && epoll_fd >= 0) | ||
266 | { | ||
267 | if (fcntl(epoll_fd, F_GETFD) < 0) | ||
268 | { | ||
269 | ERR("arghhh you caught me! report a backtrace to edevel!"); | ||
270 | pause(); | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | static inline void | ||
276 | _ecore_try_add_to_call_list(Ecore_Fd_Handler *fdh) | ||
277 | { | ||
278 | /* check if this fdh is already in the list */ | ||
279 | if (fdh->next_ready) | ||
280 | return; | ||
281 | if (fdh->read_active || fdh->write_active || fdh->error_active) | ||
282 | { | ||
283 | /* | ||
284 | * make sure next_ready is non-null by pointing to ourselves | ||
285 | * use that to indicate this fdh is in the ready list | ||
286 | * insert at the head of the list to avoid trouble | ||
287 | */ | ||
288 | fdh->next_ready = fd_handlers_to_call ? fd_handlers_to_call : fdh; | ||
289 | fd_handlers_to_call = fdh; | ||
290 | } | ||
291 | } | ||
292 | |||
293 | static inline int | ||
294 | _ecore_get_epoll_fd(void) | ||
295 | { | ||
296 | if (epoll_pid && epoll_pid != getpid()) | ||
297 | { | ||
298 | /* forked! */ | ||
299 | _ecore_main_loop_shutdown(); | ||
300 | } | ||
301 | if (epoll_pid == 0 && epoll_fd < 0) | ||
302 | { | ||
303 | _ecore_main_loop_init(); | ||
304 | } | ||
305 | return epoll_fd; | ||
306 | } | ||
307 | |||
308 | static inline int | ||
309 | _ecore_epoll_add(int efd, | ||
310 | int fd, | ||
311 | int events, | ||
312 | void *ptr) | ||
313 | { | ||
314 | struct epoll_event ev; | ||
315 | |||
316 | memset(&ev, 0, sizeof (ev)); | ||
317 | ev.events = events; | ||
318 | ev.data.ptr = ptr; | ||
319 | INF("adding poll on %d %08x", fd, events); | ||
320 | return epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev); | ||
321 | } | ||
322 | |||
323 | static inline int | ||
324 | _ecore_poll_events_from_fdh(Ecore_Fd_Handler *fdh) | ||
325 | { | ||
326 | int events = 0; | ||
327 | if (fdh->flags & ECORE_FD_READ) events |= EPOLLIN; | ||
328 | if (fdh->flags & ECORE_FD_WRITE) events |= EPOLLOUT; | ||
329 | if (fdh->flags & ECORE_FD_ERROR) events |= EPOLLERR; | ||
330 | return events; | ||
331 | } | ||
332 | |||
333 | #ifdef USE_G_MAIN_LOOP | ||
334 | static inline int | ||
335 | _gfd_events_from_fdh(Ecore_Fd_Handler *fdh) | ||
336 | { | ||
337 | int events = 0; | ||
338 | if (fdh->flags & ECORE_FD_READ) events |= G_IO_IN; | ||
339 | if (fdh->flags & ECORE_FD_WRITE) events |= G_IO_OUT; | ||
340 | if (fdh->flags & ECORE_FD_ERROR) events |= G_IO_ERR; | ||
341 | return events; | ||
342 | } | ||
343 | |||
344 | #endif | ||
345 | |||
346 | static inline int | ||
347 | _ecore_main_fdh_poll_add(Ecore_Fd_Handler *fdh) | ||
348 | { | ||
349 | int r = 0; | ||
350 | |||
351 | if (HAVE_EPOLL && epoll_fd >= 0) | ||
352 | { | ||
353 | r = _ecore_epoll_add(_ecore_get_epoll_fd(), fdh->fd, | ||
354 | _ecore_poll_events_from_fdh(fdh), fdh); | ||
355 | } | ||
356 | else | ||
357 | { | ||
358 | #ifdef USE_G_MAIN_LOOP | ||
359 | fdh->gfd.fd = fdh->fd; | ||
360 | fdh->gfd.events = _gfd_events_from_fdh(fdh); | ||
361 | fdh->gfd.revents = 0; | ||
362 | INF("adding gpoll on %d %08x", fdh->fd, fdh->gfd.events); | ||
363 | g_source_add_poll(ecore_glib_source, &fdh->gfd); | ||
364 | #endif | ||
365 | } | ||
366 | return r; | ||
367 | } | ||
368 | |||
369 | static inline void | ||
370 | _ecore_main_fdh_poll_del(Ecore_Fd_Handler *fdh) | ||
371 | { | ||
372 | if (HAVE_EPOLL && epoll_fd >= 0) | ||
373 | { | ||
374 | struct epoll_event ev; | ||
375 | int efd = _ecore_get_epoll_fd(); | ||
376 | |||
377 | memset(&ev, 0, sizeof (ev)); | ||
378 | INF("removing poll on %d", fdh->fd); | ||
379 | /* could get an EBADF if somebody closed the FD before removing it */ | ||
380 | if ((epoll_ctl(efd, EPOLL_CTL_DEL, fdh->fd, &ev) < 0)) | ||
381 | { | ||
382 | if (errno == EBADF) | ||
383 | { | ||
384 | WRN("fd %d was closed, can't remove from epoll - reinit!", | ||
385 | fdh->fd); | ||
386 | _ecore_main_loop_shutdown(); | ||
387 | _ecore_main_loop_init(); | ||
388 | } | ||
389 | else | ||
390 | { | ||
391 | ERR("Failed to delete epoll fd %d! (errno=%d)", fdh->fd, errno); | ||
392 | } | ||
393 | } | ||
394 | } | ||
395 | else | ||
396 | { | ||
397 | #ifdef USE_G_MAIN_LOOP | ||
398 | fdh->gfd.fd = fdh->fd; | ||
399 | fdh->gfd.events = _gfd_events_from_fdh(fdh); | ||
400 | fdh->gfd.revents = 0; | ||
401 | INF("adding gpoll on %d %08x", fdh->fd, fdh->gfd.events); | ||
402 | g_source_add_poll(ecore_glib_source, &fdh->gfd); | ||
403 | #endif | ||
404 | } | ||
405 | } | ||
406 | |||
407 | static inline int | ||
408 | _ecore_main_fdh_poll_modify(Ecore_Fd_Handler *fdh) | ||
409 | { | ||
410 | int r = 0; | ||
411 | if (HAVE_EPOLL && epoll_fd >= 0) | ||
412 | { | ||
413 | struct epoll_event ev; | ||
414 | int efd = _ecore_get_epoll_fd(); | ||
415 | |||
416 | memset(&ev, 0, sizeof (ev)); | ||
417 | ev.events = _ecore_poll_events_from_fdh(fdh); | ||
418 | ev.data.ptr = fdh; | ||
419 | INF("modifing epoll on %d to %08x", fdh->fd, ev.events); | ||
420 | r = epoll_ctl(efd, EPOLL_CTL_MOD, fdh->fd, &ev); | ||
421 | } | ||
422 | else | ||
423 | { | ||
424 | #ifdef USE_G_MAIN_LOOP | ||
425 | fdh->gfd.fd = fdh->fd; | ||
426 | fdh->gfd.events = _gfd_events_from_fdh(fdh); | ||
427 | fdh->gfd.revents = 0; | ||
428 | INF("modifing gpoll on %d to %08x", fdh->fd, fdh->gfd.events); | ||
429 | #endif | ||
430 | } | ||
431 | return r; | ||
432 | } | ||
433 | |||
434 | static inline int | ||
435 | _ecore_main_fdh_epoll_mark_active(void) | ||
436 | { | ||
437 | struct epoll_event ev[32]; | ||
438 | int i, ret; | ||
439 | int efd = _ecore_get_epoll_fd(); | ||
440 | |||
441 | memset(&ev, 0, sizeof (ev)); | ||
442 | ret = epoll_wait(efd, ev, sizeof(ev) / sizeof(struct epoll_event), 0); | ||
443 | if (ret < 0) | ||
444 | { | ||
445 | if (errno == EINTR) return -1; | ||
446 | ERR("epoll_wait failed %d", errno); | ||
447 | return -1; | ||
448 | } | ||
449 | |||
450 | for (i = 0; i < ret; i++) | ||
451 | { | ||
452 | Ecore_Fd_Handler *fdh; | ||
453 | |||
454 | fdh = ev[i].data.ptr; | ||
455 | if (!ECORE_MAGIC_CHECK(fdh, ECORE_MAGIC_FD_HANDLER)) | ||
456 | { | ||
457 | ECORE_MAGIC_FAIL(fdh, ECORE_MAGIC_FD_HANDLER, | ||
458 | "_ecore_main_fdh_epoll_mark_active"); | ||
459 | continue; | ||
460 | } | ||
461 | if (fdh->delete_me) | ||
462 | { | ||
463 | ERR("deleted fd in epoll"); | ||
464 | continue; | ||
465 | } | ||
466 | |||
467 | if (ev[i].events & EPOLLIN) | ||
468 | fdh->read_active = EINA_TRUE; | ||
469 | if (ev[i].events & EPOLLOUT) | ||
470 | fdh->write_active = EINA_TRUE; | ||
471 | if (ev[i].events & EPOLLERR) | ||
472 | fdh->error_active = EINA_TRUE; | ||
473 | |||
474 | _ecore_try_add_to_call_list(fdh); | ||
475 | } | ||
476 | |||
477 | return ret; | ||
478 | } | ||
479 | |||
480 | #ifdef USE_G_MAIN_LOOP | ||
481 | |||
482 | static inline int | ||
483 | _ecore_main_fdh_glib_mark_active(void) | ||
484 | { | ||
485 | Ecore_Fd_Handler *fdh; | ||
486 | int ret = 0; | ||
487 | |||
488 | /* call the prepare callback for all handlers */ | ||
489 | EINA_INLIST_FOREACH(fd_handlers, fdh) | ||
490 | { | ||
491 | if (fdh->delete_me) | ||
492 | continue; | ||
493 | |||
494 | if (fdh->gfd.revents & G_IO_IN) | ||
495 | fdh->read_active = EINA_TRUE; | ||
496 | if (fdh->gfd.revents & G_IO_OUT) | ||
497 | fdh->write_active = EINA_TRUE; | ||
498 | if (fdh->gfd.revents & G_IO_ERR) | ||
499 | fdh->error_active = EINA_TRUE; | ||
500 | |||
501 | _ecore_try_add_to_call_list(fdh); | ||
502 | |||
503 | if (fdh->gfd.revents & (G_IO_IN | G_IO_OUT | G_IO_ERR)) ret++; | ||
504 | } | ||
505 | |||
506 | return ret; | ||
507 | } | ||
508 | |||
509 | /* like we are about to enter main_loop_select in _ecore_main_select */ | ||
510 | static gboolean | ||
511 | _ecore_main_gsource_prepare(GSource *source __UNUSED__, | ||
512 | gint *next_time) | ||
513 | { | ||
514 | gboolean ready = FALSE; | ||
515 | |||
516 | _ecore_lock(); | ||
517 | in_main_loop++; | ||
518 | |||
519 | if (!ecore_idling && !_ecore_glib_idle_enterer_called) | ||
520 | { | ||
521 | _ecore_time_loop_time = ecore_time_get(); | ||
522 | _ecore_timer_expired_timers_call(_ecore_time_loop_time); | ||
523 | _ecore_timer_cleanup(); | ||
524 | |||
525 | _ecore_idle_enterer_call(); | ||
526 | _ecore_throttle(); | ||
527 | _ecore_glib_idle_enterer_called = FALSE; | ||
528 | |||
529 | if (fd_handlers_with_buffer) | ||
530 | _ecore_main_fd_handlers_buf_call(); | ||
531 | } | ||
532 | |||
533 | _ecore_signal_received_process(); | ||
534 | |||
535 | /* don't check fds if somebody quit */ | ||
536 | if (g_main_loop_is_running(ecore_main_loop)) | ||
537 | { | ||
538 | /* only set idling state in dispatch */ | ||
539 | if (ecore_idling && !_ecore_idler_exist() && !_ecore_event_exist()) | ||
540 | { | ||
541 | if (_ecore_timers_exists()) | ||
542 | { | ||
543 | int r = -1; | ||
544 | double t = _ecore_timer_next_get(); | ||
545 | if (timer_fd >= 0 && t > 0.0) | ||
546 | { | ||
547 | struct itimerspec ts; | ||
548 | |||
549 | ts.it_interval.tv_sec = 0; | ||
550 | ts.it_interval.tv_nsec = 0; | ||
551 | ts.it_value.tv_sec = t; | ||
552 | ts.it_value.tv_nsec = fmod(t * NS_PER_SEC, NS_PER_SEC); | ||
553 | |||
554 | /* timerfd cannot sleep for 0 time */ | ||
555 | if (ts.it_value.tv_sec || ts.it_value.tv_nsec) | ||
556 | { | ||
557 | r = timerfd_settime(timer_fd, 0, &ts, NULL); | ||
558 | if (r < 0) | ||
559 | { | ||
560 | ERR("timer set returned %d (errno=%d)", r, errno); | ||
561 | close(timer_fd); | ||
562 | timer_fd = -1; | ||
563 | } | ||
564 | else | ||
565 | INF("sleeping for %ld s %06ldus", | ||
566 | ts.it_value.tv_sec, | ||
567 | ts.it_value.tv_nsec / 1000); | ||
568 | } | ||
569 | } | ||
570 | if (r == -1) | ||
571 | { | ||
572 | *next_time = ceil(t * 1000.0); | ||
573 | if (t == 0.0) | ||
574 | ready = TRUE; | ||
575 | } | ||
576 | } | ||
577 | else | ||
578 | *next_time = -1; | ||
579 | } | ||
580 | else | ||
581 | { | ||
582 | *next_time = 0; | ||
583 | if (_ecore_event_exist()) | ||
584 | ready = TRUE; | ||
585 | } | ||
586 | |||
587 | if (fd_handlers_with_prep) | ||
588 | _ecore_main_prepare_handlers(); | ||
589 | } | ||
590 | else | ||
591 | ready = TRUE; | ||
592 | |||
593 | in_main_loop--; | ||
594 | INF("leave, timeout = %d", *next_time); | ||
595 | _ecore_unlock(); | ||
596 | |||
597 | /* ready if we're not running (about to quit) */ | ||
598 | return ready; | ||
599 | } | ||
600 | |||
601 | static gboolean | ||
602 | _ecore_main_gsource_check(GSource *source __UNUSED__) | ||
603 | { | ||
604 | gboolean ret = FALSE; | ||
605 | |||
606 | _ecore_lock(); | ||
607 | in_main_loop++; | ||
608 | |||
609 | /* check if old timers expired */ | ||
610 | if (ecore_idling && !_ecore_idler_exist() && !_ecore_event_exist()) | ||
611 | { | ||
612 | if (timer_fd >= 0) | ||
613 | { | ||
614 | uint64_t count = 0; | ||
615 | int r = read(timer_fd, &count, sizeof count); | ||
616 | if (r == -1 && errno == EAGAIN) | ||
617 | ; | ||
618 | else if (r == sizeof count) | ||
619 | ret = TRUE; | ||
620 | else | ||
621 | { | ||
622 | /* unexpected things happened... fail back to old way */ | ||
623 | ERR("timer read returned %d (errno=%d)", r, errno); | ||
624 | close(timer_fd); | ||
625 | timer_fd = -1; | ||
626 | } | ||
627 | } | ||
628 | } | ||
629 | else | ||
630 | ret = TRUE; | ||
631 | |||
632 | /* check if fds are ready */ | ||
633 | if (HAVE_EPOLL && epoll_fd >= 0) | ||
634 | ecore_fds_ready = (_ecore_main_fdh_epoll_mark_active() > 0); | ||
635 | else | ||
636 | ecore_fds_ready = (_ecore_main_fdh_glib_mark_active() > 0); | ||
637 | _ecore_main_fd_handlers_cleanup(); | ||
638 | if (ecore_fds_ready) | ||
639 | ret = TRUE; | ||
640 | |||
641 | /* check timers after updating loop time */ | ||
642 | if (!ret && _ecore_timers_exists()) | ||
643 | ret = (0.0 == _ecore_timer_next_get()); | ||
644 | |||
645 | in_main_loop--; | ||
646 | _ecore_unlock(); | ||
647 | |||
648 | return ret; | ||
649 | } | ||
650 | |||
651 | /* like we just came out of main_loop_select in _ecore_main_select */ | ||
652 | static gboolean | ||
653 | _ecore_main_gsource_dispatch(GSource *source __UNUSED__, | ||
654 | GSourceFunc callback __UNUSED__, | ||
655 | gpointer user_data __UNUSED__) | ||
656 | { | ||
657 | gboolean events_ready, timers_ready, idlers_ready; | ||
658 | double next_time; | ||
659 | |||
660 | _ecore_lock(); | ||
661 | _ecore_time_loop_time = ecore_time_get(); | ||
662 | _ecore_timer_enable_new(); | ||
663 | next_time = _ecore_timer_next_get(); | ||
664 | |||
665 | events_ready = _ecore_event_exist(); | ||
666 | timers_ready = _ecore_timers_exists() && (0.0 == next_time); | ||
667 | idlers_ready = _ecore_idler_exist(); | ||
668 | |||
669 | in_main_loop++; | ||
670 | INF("enter idling=%d fds=%d events=%d timers=%d (next=%.2f) idlers=%d", | ||
671 | ecore_idling, ecore_fds_ready, events_ready, | ||
672 | timers_ready, next_time, idlers_ready); | ||
673 | |||
674 | if (ecore_idling && events_ready) | ||
675 | { | ||
676 | _ecore_idle_exiter_call(); | ||
677 | ecore_idling = 0; | ||
678 | } | ||
679 | else if (!ecore_idling && !events_ready) | ||
680 | { | ||
681 | ecore_idling = 1; | ||
682 | } | ||
683 | |||
684 | if (ecore_idling) | ||
685 | { | ||
686 | _ecore_idler_all_call(); | ||
687 | |||
688 | events_ready = _ecore_event_exist(); | ||
689 | |||
690 | if (ecore_fds_ready || events_ready || timers_ready) | ||
691 | { | ||
692 | _ecore_idle_exiter_call(); | ||
693 | ecore_idling = 0; | ||
694 | } | ||
695 | } | ||
696 | |||
697 | /* process events */ | ||
698 | if (!ecore_idling) | ||
699 | { | ||
700 | _ecore_main_fd_handlers_call(); | ||
701 | if (fd_handlers_with_buffer) | ||
702 | _ecore_main_fd_handlers_buf_call(); | ||
703 | _ecore_signal_received_process(); | ||
704 | _ecore_event_call(); | ||
705 | _ecore_main_fd_handlers_cleanup(); | ||
706 | |||
707 | _ecore_timer_expired_timers_call(_ecore_time_loop_time); | ||
708 | _ecore_timer_cleanup(); | ||
709 | |||
710 | _ecore_idle_enterer_call(); | ||
711 | _ecore_throttle(); | ||
712 | _ecore_glib_idle_enterer_called = TRUE; | ||
713 | |||
714 | if (fd_handlers_with_buffer) | ||
715 | _ecore_main_fd_handlers_buf_call(); | ||
716 | } | ||
717 | |||
718 | in_main_loop--; | ||
719 | _ecore_unlock(); | ||
720 | |||
721 | return TRUE; /* what should be returned here? */ | ||
722 | } | ||
723 | |||
724 | static void | ||
725 | _ecore_main_gsource_finalize(GSource *source __UNUSED__) | ||
726 | { | ||
727 | } | ||
728 | |||
729 | static GSourceFuncs ecore_gsource_funcs = | ||
730 | { | ||
731 | .prepare = _ecore_main_gsource_prepare, | ||
732 | .check = _ecore_main_gsource_check, | ||
733 | .dispatch = _ecore_main_gsource_dispatch, | ||
734 | .finalize = _ecore_main_gsource_finalize, | ||
735 | }; | ||
736 | |||
737 | #endif | ||
738 | |||
739 | void | ||
740 | _ecore_main_loop_init(void) | ||
741 | { | ||
742 | epoll_fd = epoll_create(1); | ||
743 | if (epoll_fd < 0) | ||
744 | WRN("Failed to create epoll fd!"); | ||
745 | epoll_pid = getpid(); | ||
746 | |||
747 | /* add polls on all our file descriptors */ | ||
748 | Ecore_Fd_Handler *fdh; | ||
749 | EINA_INLIST_FOREACH(fd_handlers, fdh) | ||
750 | { | ||
751 | if (fdh->delete_me) | ||
752 | continue; | ||
753 | _ecore_epoll_add(epoll_fd, fdh->fd, | ||
754 | _ecore_poll_events_from_fdh(fdh), fdh); | ||
755 | _ecore_main_fdh_poll_add(fdh); | ||
756 | } | ||
757 | |||
758 | /* setup for the g_main_loop only integration */ | ||
759 | #ifdef USE_G_MAIN_LOOP | ||
760 | ecore_glib_source = g_source_new(&ecore_gsource_funcs, sizeof (GSource)); | ||
761 | if (!ecore_glib_source) | ||
762 | CRIT("Failed to create glib source for epoll!"); | ||
763 | else | ||
764 | { | ||
765 | g_source_set_priority(ecore_glib_source, G_PRIORITY_HIGH_IDLE + 20); | ||
766 | if (HAVE_EPOLL && epoll_fd >= 0) | ||
767 | { | ||
768 | /* epoll multiplexes fds into the g_main_loop */ | ||
769 | ecore_epoll_fd.fd = epoll_fd; | ||
770 | ecore_epoll_fd.events = G_IO_IN; | ||
771 | ecore_epoll_fd.revents = 0; | ||
772 | g_source_add_poll(ecore_glib_source, &ecore_epoll_fd); | ||
773 | } | ||
774 | |||
775 | /* timerfd gives us better than millisecond accuracy in g_main_loop */ | ||
776 | timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); | ||
777 | if (timer_fd < 0) | ||
778 | WRN("failed to create timer fd!"); | ||
779 | else | ||
780 | { | ||
781 | ecore_timer_fd.fd = timer_fd; | ||
782 | ecore_timer_fd.events = G_IO_IN; | ||
783 | ecore_timer_fd.revents = 0; | ||
784 | g_source_add_poll(ecore_glib_source, &ecore_timer_fd); | ||
785 | } | ||
786 | |||
787 | ecore_glib_source_id = g_source_attach(ecore_glib_source, NULL); | ||
788 | if (ecore_glib_source_id <= 0) | ||
789 | CRIT("Failed to attach glib source to default context"); | ||
790 | } | ||
791 | #endif | ||
792 | } | ||
793 | |||
794 | void | ||
795 | _ecore_main_loop_shutdown(void) | ||
796 | { | ||
797 | #ifdef USE_G_MAIN_LOOP | ||
798 | if (ecore_glib_source) | ||
799 | { | ||
800 | g_source_destroy(ecore_glib_source); | ||
801 | ecore_glib_source = NULL; | ||
802 | } | ||
803 | #endif | ||
804 | |||
805 | if (epoll_fd >= 0) | ||
806 | { | ||
807 | close(epoll_fd); | ||
808 | epoll_fd = -1; | ||
809 | } | ||
810 | epoll_pid = 0; | ||
811 | |||
812 | if (timer_fd >= 0) | ||
813 | { | ||
814 | close(timer_fd); | ||
815 | timer_fd = -1; | ||
816 | } | ||
817 | } | ||
818 | |||
819 | void * | ||
820 | _ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler) | ||
821 | { | ||
822 | if (fd_handler->delete_me) | ||
823 | { | ||
824 | ERR("fdh %p deleted twice", fd_handler); | ||
825 | return NULL; | ||
826 | } | ||
827 | |||
828 | _ecore_main_fdh_poll_del(fd_handler); | ||
829 | fd_handler->delete_me = EINA_TRUE; | ||
830 | fd_handlers_to_delete = eina_list_append(fd_handlers_to_delete, fd_handler); | ||
831 | if (fd_handler->prep_func && fd_handlers_with_prep) | ||
832 | fd_handlers_with_prep = eina_list_remove(fd_handlers_with_prep, fd_handler); | ||
833 | if (fd_handler->buf_func && fd_handlers_with_buffer) | ||
834 | fd_handlers_with_buffer = eina_list_remove(fd_handlers_with_buffer, fd_handler); | ||
835 | return fd_handler->data; | ||
836 | } | ||
837 | |||
838 | /** | ||
839 | * @addtogroup Ecore_Main_Loop_Group | ||
840 | * | ||
841 | * @{ | ||
842 | */ | ||
843 | |||
844 | /** | ||
845 | * Runs a single iteration of the main loop to process everything on the | ||
846 | * queue. | ||
847 | * | ||
848 | * It does everything that is already done inside an @c Ecore main loop, like | ||
849 | * checking for expired timers, idlers, etc. But it will do it only once and | ||
850 | * return, instead of keep watching for new events. | ||
851 | * | ||
852 | * DO NOT use this function unless you are the person God comes to ask for | ||
853 | * advice when He has trouble managing the Universe. | ||
854 | */ | ||
855 | |||
856 | EAPI int | ||
857 | ecore_main_loop_iterate_may_block(int may_block) | ||
858 | { | ||
859 | #ifndef USE_G_MAIN_LOOP | ||
860 | _ecore_lock(); | ||
861 | in_main_loop++; | ||
862 | _ecore_main_loop_iterate_internal(!may_block); | ||
863 | in_main_loop--; | ||
864 | _ecore_unlock(); | ||
865 | return _ecore_event_exist(); | ||
866 | #else | ||
867 | return g_main_context_iteration(NULL, may_block); | ||
868 | #endif | ||
869 | } | ||
870 | EAPI void | ||
871 | ecore_main_loop_iterate(void) | ||
872 | { | ||
873 | #ifndef USE_G_MAIN_LOOP | ||
874 | _ecore_lock(); | ||
875 | _ecore_main_loop_iterate_internal(1); | ||
876 | _ecore_unlock(); | ||
877 | #else | ||
878 | g_main_context_iteration(NULL, 0); | ||
879 | #endif | ||
880 | } | ||
881 | |||
882 | /** | ||
883 | * Runs the application main loop. | ||
884 | * | ||
885 | * This function will not return until @ref ecore_main_loop_quit is called. It | ||
886 | * will check for expired timers, idlers, file descriptors being watched by fd | ||
887 | * handlers, etc. Once everything is done, before entering again on idle state, | ||
888 | * any callback set as @c Idle_Enterer will be called. | ||
889 | * | ||
890 | * Each main loop iteration is done by calling ecore_main_loop_iterate() | ||
891 | * internally. | ||
892 | * | ||
893 | * The polling (select) function used can be changed with | ||
894 | * ecore_main_loop_select_func_set(). | ||
895 | * | ||
896 | * The function used to check for file descriptors, events, and that has a | ||
897 | * timeout for the timers can be changed using | ||
898 | * ecore_main_loop_select_func_set(). | ||
899 | */ | ||
900 | EAPI void | ||
901 | ecore_main_loop_begin(void) | ||
902 | { | ||
903 | #ifndef USE_G_MAIN_LOOP | ||
904 | _ecore_lock(); | ||
905 | in_main_loop++; | ||
906 | while (do_quit == 0) _ecore_main_loop_iterate_internal(0); | ||
907 | do_quit = 0; | ||
908 | in_main_loop--; | ||
909 | _ecore_unlock(); | ||
910 | #else | ||
911 | if (!do_quit) | ||
912 | { | ||
913 | if (!ecore_main_loop) | ||
914 | ecore_main_loop = g_main_loop_new(NULL, FALSE); | ||
915 | g_main_loop_run(ecore_main_loop); | ||
916 | } | ||
917 | do_quit = 0; | ||
918 | #endif | ||
919 | } | ||
920 | |||
921 | /** | ||
922 | * Quits the main loop once all the events currently on the queue have | ||
923 | * been processed. | ||
924 | * | ||
925 | * This function returns immediately, but will mark the ecore_main_loop_begin() | ||
926 | * function to return at the end of the current main loop iteration. | ||
927 | */ | ||
928 | EAPI void | ||
929 | ecore_main_loop_quit(void) | ||
930 | { | ||
931 | do_quit = 1; | ||
932 | #ifdef USE_G_MAIN_LOOP | ||
933 | if (ecore_main_loop) | ||
934 | g_main_loop_quit(ecore_main_loop); | ||
935 | #endif | ||
936 | } | ||
937 | |||
938 | /** | ||
939 | * Sets the function to use when monitoring multiple file descriptors, | ||
940 | * and waiting until one of more of the file descriptors before ready | ||
941 | * for some class of I/O operation. | ||
942 | * | ||
943 | * This function will be used instead of the system call select and | ||
944 | * could possible be used to integrate the Ecore event loop with an | ||
945 | * external event loop. | ||
946 | * | ||
947 | * @warning you don't know how to use, don't even try to use it. | ||
948 | * | ||
949 | */ | ||
950 | EAPI void | ||
951 | ecore_main_loop_select_func_set(Ecore_Select_Function func) | ||
952 | { | ||
953 | main_loop_select = func; | ||
954 | } | ||
955 | |||
956 | /** | ||
957 | * Gets the select function set by ecore_select_func_set(), | ||
958 | * or the native select function if none was set. | ||
959 | * | ||
960 | */ | ||
961 | EAPI Ecore_Select_Function | ||
962 | ecore_main_loop_select_func_get(void) | ||
963 | { | ||
964 | return main_loop_select; | ||
965 | } | ||
966 | |||
967 | EAPI Ecore_Fd_Handler * | ||
968 | ecore_main_fd_handler_add(int fd, | ||
969 | Ecore_Fd_Handler_Flags flags, | ||
970 | Ecore_Fd_Cb func, | ||
971 | const void *data, | ||
972 | Ecore_Fd_Cb buf_func, | ||
973 | const void *buf_data) | ||
974 | { | ||
975 | Ecore_Fd_Handler *fdh = NULL; | ||
976 | |||
977 | _ecore_lock(); | ||
978 | |||
979 | if ((fd < 0) || (flags == 0) || (!func)) goto unlock; | ||
980 | |||
981 | fdh = ecore_fd_handler_calloc(1); | ||
982 | if (!fdh) goto unlock; | ||
983 | ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER); | ||
984 | fdh->next_ready = NULL; | ||
985 | fdh->fd = fd; | ||
986 | fdh->flags = flags; | ||
987 | if (_ecore_main_fdh_poll_add(fdh) < 0) | ||
988 | { | ||
989 | int err = errno; | ||
990 | ERR("Failed to add poll on fd %d (errno = %d: %s)!", fd, err, strerror(err)); | ||
991 | ecore_fd_handler_mp_free(fdh); | ||
992 | fdh = NULL; | ||
993 | goto unlock; | ||
994 | } | ||
995 | fdh->read_active = EINA_FALSE; | ||
996 | fdh->write_active = EINA_FALSE; | ||
997 | fdh->error_active = EINA_FALSE; | ||
998 | fdh->delete_me = EINA_FALSE; | ||
999 | fdh->func = func; | ||
1000 | fdh->data = (void *)data; | ||
1001 | fdh->buf_func = buf_func; | ||
1002 | if (buf_func) | ||
1003 | fd_handlers_with_buffer = eina_list_append(fd_handlers_with_buffer, fdh); | ||
1004 | fdh->buf_data = (void *)buf_data; | ||
1005 | fd_handlers = (Ecore_Fd_Handler *) | ||
1006 | eina_inlist_append(EINA_INLIST_GET(fd_handlers), | ||
1007 | EINA_INLIST_GET(fdh)); | ||
1008 | unlock: | ||
1009 | _ecore_unlock(); | ||
1010 | |||
1011 | return fdh; | ||
1012 | } | ||
1013 | |||
1014 | #ifdef _WIN32 | ||
1015 | EAPI Ecore_Win32_Handler * | ||
1016 | ecore_main_win32_handler_add(void *h, | ||
1017 | Ecore_Win32_Handle_Cb func, | ||
1018 | const void *data) | ||
1019 | { | ||
1020 | Ecore_Win32_Handler *wh; | ||
1021 | |||
1022 | if (!h || !func) return NULL; | ||
1023 | |||
1024 | wh = ecore_win32_handler_calloc(1); | ||
1025 | if (!wh) return NULL; | ||
1026 | ECORE_MAGIC_SET(wh, ECORE_MAGIC_WIN32_HANDLER); | ||
1027 | wh->h = (HANDLE)h; | ||
1028 | wh->delete_me = EINA_FALSE; | ||
1029 | wh->func = func; | ||
1030 | wh->data = (void *)data; | ||
1031 | win32_handlers = (Ecore_Win32_Handler *) | ||
1032 | eina_inlist_append(EINA_INLIST_GET(win32_handlers), | ||
1033 | EINA_INLIST_GET(wh)); | ||
1034 | return wh; | ||
1035 | } | ||
1036 | |||
1037 | #else | ||
1038 | EAPI Ecore_Win32_Handler * | ||
1039 | ecore_main_win32_handler_add(void *h __UNUSED__, | ||
1040 | Ecore_Win32_Handle_Cb func __UNUSED__, | ||
1041 | const void *data __UNUSED__) | ||
1042 | { | ||
1043 | return NULL; | ||
1044 | } | ||
1045 | |||
1046 | #endif | ||
1047 | |||
1048 | EAPI void * | ||
1049 | ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler) | ||
1050 | { | ||
1051 | void *ret = NULL; | ||
1052 | |||
1053 | _ecore_lock(); | ||
1054 | |||
1055 | if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER)) | ||
1056 | { | ||
1057 | ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER, | ||
1058 | "ecore_main_fd_handler_del"); | ||
1059 | goto unlock; | ||
1060 | } | ||
1061 | ret = _ecore_main_fd_handler_del(fd_handler); | ||
1062 | unlock: | ||
1063 | _ecore_unlock(); | ||
1064 | return ret; | ||
1065 | } | ||
1066 | |||
1067 | #ifdef _WIN32 | ||
1068 | EAPI void * | ||
1069 | ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler) | ||
1070 | { | ||
1071 | if (!ECORE_MAGIC_CHECK(win32_handler, ECORE_MAGIC_WIN32_HANDLER)) | ||
1072 | { | ||
1073 | ECORE_MAGIC_FAIL(win32_handler, ECORE_MAGIC_WIN32_HANDLER, | ||
1074 | "ecore_main_win32_handler_del"); | ||
1075 | return NULL; | ||
1076 | } | ||
1077 | win32_handler->delete_me = EINA_TRUE; | ||
1078 | win32_handlers_delete_me = EINA_TRUE; | ||
1079 | return win32_handler->data; | ||
1080 | } | ||
1081 | |||
1082 | #else | ||
1083 | EAPI void * | ||
1084 | ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler __UNUSED__) | ||
1085 | { | ||
1086 | return NULL; | ||
1087 | } | ||
1088 | |||
1089 | #endif | ||
1090 | |||
1091 | EAPI void | ||
1092 | ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler, | ||
1093 | Ecore_Fd_Prep_Cb func, | ||
1094 | const void *data) | ||
1095 | { | ||
1096 | _ecore_lock(); | ||
1097 | |||
1098 | if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER)) | ||
1099 | { | ||
1100 | ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER, | ||
1101 | "ecore_main_fd_handler_prepare_callback_set"); | ||
1102 | goto unlock; | ||
1103 | } | ||
1104 | fd_handler->prep_func = func; | ||
1105 | fd_handler->prep_data = (void *)data; | ||
1106 | if ((!fd_handlers_with_prep) || | ||
1107 | (fd_handlers_with_prep && (!eina_list_data_find(fd_handlers_with_prep, fd_handler)))) | ||
1108 | /* FIXME: THIS WILL NOT SCALE WITH LOTS OF PREP FUNCTIONS!!! */ | ||
1109 | fd_handlers_with_prep = eina_list_append(fd_handlers_with_prep, fd_handler); | ||
1110 | unlock: | ||
1111 | _ecore_unlock(); | ||
1112 | } | ||
1113 | |||
1114 | EAPI int | ||
1115 | ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler) | ||
1116 | { | ||
1117 | int fd = -1; | ||
1118 | |||
1119 | _ecore_lock(); | ||
1120 | |||
1121 | if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER)) | ||
1122 | { | ||
1123 | ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER, | ||
1124 | "ecore_main_fd_handler_fd_get"); | ||
1125 | goto unlock; | ||
1126 | } | ||
1127 | fd = fd_handler->fd; | ||
1128 | unlock: | ||
1129 | _ecore_unlock(); | ||
1130 | return fd; | ||
1131 | } | ||
1132 | |||
1133 | EAPI Eina_Bool | ||
1134 | ecore_main_fd_handler_active_get(Ecore_Fd_Handler *fd_handler, | ||
1135 | Ecore_Fd_Handler_Flags flags) | ||
1136 | { | ||
1137 | int ret = EINA_FALSE; | ||
1138 | |||
1139 | _ecore_lock(); | ||
1140 | |||
1141 | if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER)) | ||
1142 | { | ||
1143 | ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER, | ||
1144 | "ecore_main_fd_handler_active_get"); | ||
1145 | goto unlock; | ||
1146 | } | ||
1147 | if ((flags & ECORE_FD_READ) && (fd_handler->read_active)) ret = EINA_TRUE; | ||
1148 | if ((flags & ECORE_FD_WRITE) && (fd_handler->write_active)) ret = EINA_TRUE; | ||
1149 | if ((flags & ECORE_FD_ERROR) && (fd_handler->error_active)) ret = EINA_TRUE; | ||
1150 | unlock: | ||
1151 | _ecore_unlock(); | ||
1152 | return ret; | ||
1153 | } | ||
1154 | |||
1155 | EAPI void | ||
1156 | ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, | ||
1157 | Ecore_Fd_Handler_Flags flags) | ||
1158 | { | ||
1159 | int ret; | ||
1160 | |||
1161 | _ecore_lock(); | ||
1162 | |||
1163 | if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER)) | ||
1164 | { | ||
1165 | ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER, | ||
1166 | "ecore_main_fd_handler_active_set"); | ||
1167 | goto unlock; | ||
1168 | } | ||
1169 | fd_handler->flags = flags; | ||
1170 | ret = _ecore_main_fdh_poll_modify(fd_handler); | ||
1171 | if (ret < 0) | ||
1172 | { | ||
1173 | ERR("Failed to mod epoll fd %d: %s!", fd_handler->fd, strerror(ret)); | ||
1174 | } | ||
1175 | unlock: | ||
1176 | _ecore_unlock(); | ||
1177 | } | ||
1178 | |||
1179 | /** | ||
1180 | * @} | ||
1181 | */ | ||
1182 | |||
1183 | void | ||
1184 | _ecore_main_shutdown(void) | ||
1185 | { | ||
1186 | if (in_main_loop) | ||
1187 | { | ||
1188 | ERR("\n" | ||
1189 | "*** ECORE WARINING: Calling ecore_shutdown() while still in the main loop.\n" | ||
1190 | "*** Program may crash or behave strangely now."); | ||
1191 | return; | ||
1192 | } | ||
1193 | while (fd_handlers) | ||
1194 | { | ||
1195 | Ecore_Fd_Handler *fdh; | ||
1196 | |||
1197 | fdh = fd_handlers; | ||
1198 | fd_handlers = (Ecore_Fd_Handler *)eina_inlist_remove(EINA_INLIST_GET(fd_handlers), | ||
1199 | EINA_INLIST_GET(fdh)); | ||
1200 | ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE); | ||
1201 | ecore_fd_handler_mp_free(fdh); | ||
1202 | } | ||
1203 | if (fd_handlers_with_buffer) | ||
1204 | fd_handlers_with_buffer = eina_list_free(fd_handlers_with_buffer); | ||
1205 | if (fd_handlers_with_prep) | ||
1206 | fd_handlers_with_prep = eina_list_free(fd_handlers_with_prep); | ||
1207 | if (fd_handlers_to_delete) | ||
1208 | fd_handlers_to_delete = eina_list_free(fd_handlers_to_delete); | ||
1209 | |||
1210 | fd_handlers_to_call = NULL; | ||
1211 | fd_handlers_to_call_current = NULL; | ||
1212 | fd_handlers_to_delete = NULL; | ||
1213 | fd_handler_current = NULL; | ||
1214 | |||
1215 | #ifdef _WIN32 | ||
1216 | while (win32_handlers) | ||
1217 | { | ||
1218 | Ecore_Win32_Handler *wh; | ||
1219 | |||
1220 | wh = win32_handlers; | ||
1221 | win32_handlers = (Ecore_Win32_Handler *)eina_inlist_remove(EINA_INLIST_GET(win32_handlers), | ||
1222 | EINA_INLIST_GET(wh)); | ||
1223 | ECORE_MAGIC_SET(wh, ECORE_MAGIC_NONE); | ||
1224 | ecore_win32_handler_mp_free(wh); | ||
1225 | } | ||
1226 | win32_handlers_delete_me = EINA_FALSE; | ||
1227 | win32_handler_current = NULL; | ||
1228 | #endif | ||
1229 | } | ||
1230 | |||
1231 | static void | ||
1232 | _ecore_main_prepare_handlers(void) | ||
1233 | { | ||
1234 | Ecore_Fd_Handler *fdh; | ||
1235 | Eina_List *l, *l2; | ||
1236 | |||
1237 | /* call the prepare callback for all handlers with prep functions */ | ||
1238 | EINA_LIST_FOREACH_SAFE(fd_handlers_with_prep, l, l2, fdh) | ||
1239 | { | ||
1240 | if (!fdh) | ||
1241 | { | ||
1242 | fd_handlers_with_prep = eina_list_remove_list(l, fd_handlers_with_prep); | ||
1243 | continue; | ||
1244 | } | ||
1245 | if (!fdh->delete_me && fdh->prep_func) | ||
1246 | { | ||
1247 | fdh->references++; | ||
1248 | _ecore_call_prep_cb(fdh->prep_func, fdh->prep_data, fdh); | ||
1249 | fdh->references--; | ||
1250 | } | ||
1251 | else | ||
1252 | fd_handlers_with_prep = eina_list_remove_list(fd_handlers_with_prep, l); | ||
1253 | } | ||
1254 | } | ||
1255 | |||
1256 | #ifndef USE_G_MAIN_LOOP | ||
1257 | static int | ||
1258 | _ecore_main_select(double timeout) | ||
1259 | { | ||
1260 | struct timeval tv, *t; | ||
1261 | fd_set rfds, wfds, exfds; | ||
1262 | int max_fd; | ||
1263 | int ret; | ||
1264 | |||
1265 | t = NULL; | ||
1266 | if ((!ECORE_FINITE(timeout)) || (timeout == 0.0)) /* finite() tests for NaN, too big, too small, and infinity. */ | ||
1267 | { | ||
1268 | tv.tv_sec = 0; | ||
1269 | tv.tv_usec = 0; | ||
1270 | t = &tv; | ||
1271 | } | ||
1272 | else if (timeout > 0.0) | ||
1273 | { | ||
1274 | int sec, usec; | ||
1275 | |||
1276 | #ifdef FIX_HZ | ||
1277 | timeout += (0.5 / HZ); | ||
1278 | sec = (int)timeout; | ||
1279 | usec = (int)((timeout - (double)sec) * 1000000); | ||
1280 | #else | ||
1281 | sec = (int)timeout; | ||
1282 | usec = (int)((timeout - (double)sec) * 1000000); | ||
1283 | #endif | ||
1284 | tv.tv_sec = sec; | ||
1285 | tv.tv_usec = usec; | ||
1286 | t = &tv; | ||
1287 | } | ||
1288 | max_fd = 0; | ||
1289 | FD_ZERO(&rfds); | ||
1290 | FD_ZERO(&wfds); | ||
1291 | FD_ZERO(&exfds); | ||
1292 | |||
1293 | /* call the prepare callback for all handlers */ | ||
1294 | if (fd_handlers_with_prep) | ||
1295 | _ecore_main_prepare_handlers(); | ||
1296 | |||
1297 | if (!HAVE_EPOLL || epoll_fd < 0) | ||
1298 | { | ||
1299 | Ecore_Fd_Handler *fdh; | ||
1300 | |||
1301 | EINA_INLIST_FOREACH(fd_handlers, fdh) | ||
1302 | { | ||
1303 | if (!fdh->delete_me) | ||
1304 | { | ||
1305 | if (fdh->flags & ECORE_FD_READ) | ||
1306 | { | ||
1307 | FD_SET(fdh->fd, &rfds); | ||
1308 | if (fdh->fd > max_fd) max_fd = fdh->fd; | ||
1309 | } | ||
1310 | if (fdh->flags & ECORE_FD_WRITE) | ||
1311 | { | ||
1312 | FD_SET(fdh->fd, &wfds); | ||
1313 | if (fdh->fd > max_fd) max_fd = fdh->fd; | ||
1314 | } | ||
1315 | if (fdh->flags & ECORE_FD_ERROR) | ||
1316 | { | ||
1317 | FD_SET(fdh->fd, &exfds); | ||
1318 | if (fdh->fd > max_fd) max_fd = fdh->fd; | ||
1319 | } | ||
1320 | } | ||
1321 | } | ||
1322 | } | ||
1323 | else | ||
1324 | { | ||
1325 | /* polling on the epoll fd will wake when an fd in the epoll set is active */ | ||
1326 | max_fd = _ecore_get_epoll_fd(); | ||
1327 | FD_SET(max_fd, &rfds); | ||
1328 | } | ||
1329 | |||
1330 | if (_ecore_signal_count_get()) return -1; | ||
1331 | |||
1332 | _ecore_unlock(); | ||
1333 | ret = main_loop_select(max_fd + 1, &rfds, &wfds, &exfds, t); | ||
1334 | _ecore_lock(); | ||
1335 | |||
1336 | _ecore_time_loop_time = ecore_time_get(); | ||
1337 | if (ret < 0) | ||
1338 | { | ||
1339 | #ifndef _WIN32 | ||
1340 | if (errno == EINTR) return -1; | ||
1341 | else if (errno == EBADF) | ||
1342 | _ecore_main_fd_handlers_bads_rem(); | ||
1343 | #endif | ||
1344 | } | ||
1345 | if (ret > 0) | ||
1346 | { | ||
1347 | if (HAVE_EPOLL && epoll_fd >= 0) | ||
1348 | _ecore_main_fdh_epoll_mark_active(); | ||
1349 | else | ||
1350 | { | ||
1351 | Ecore_Fd_Handler *fdh; | ||
1352 | |||
1353 | EINA_INLIST_FOREACH(fd_handlers, fdh) | ||
1354 | { | ||
1355 | if (!fdh->delete_me) | ||
1356 | { | ||
1357 | if (FD_ISSET(fdh->fd, &rfds)) | ||
1358 | fdh->read_active = EINA_TRUE; | ||
1359 | if (FD_ISSET(fdh->fd, &wfds)) | ||
1360 | fdh->write_active = EINA_TRUE; | ||
1361 | if (FD_ISSET(fdh->fd, &exfds)) | ||
1362 | fdh->error_active = EINA_TRUE; | ||
1363 | _ecore_try_add_to_call_list(fdh); | ||
1364 | } | ||
1365 | } | ||
1366 | } | ||
1367 | |||
1368 | _ecore_main_fd_handlers_cleanup(); | ||
1369 | #ifdef _WIN32 | ||
1370 | _ecore_main_win32_handlers_cleanup(); | ||
1371 | #endif | ||
1372 | return 1; | ||
1373 | } | ||
1374 | return 0; | ||
1375 | } | ||
1376 | |||
1377 | #endif | ||
1378 | |||
1379 | #ifndef _WIN32 | ||
1380 | # ifndef USE_G_MAIN_LOOP | ||
1381 | static void | ||
1382 | _ecore_main_fd_handlers_bads_rem(void) | ||
1383 | { | ||
1384 | Ecore_Fd_Handler *fdh; | ||
1385 | Eina_Inlist *l; | ||
1386 | int found = 0; | ||
1387 | |||
1388 | ERR("Removing bad fds"); | ||
1389 | for (l = EINA_INLIST_GET(fd_handlers); l; ) | ||
1390 | { | ||
1391 | fdh = (Ecore_Fd_Handler *)l; | ||
1392 | l = l->next; | ||
1393 | errno = 0; | ||
1394 | |||
1395 | if ((fcntl(fdh->fd, F_GETFD) < 0) && (errno == EBADF)) | ||
1396 | { | ||
1397 | ERR("Found bad fd at index %d", fdh->fd); | ||
1398 | if (fdh->flags & ECORE_FD_ERROR) | ||
1399 | { | ||
1400 | ERR("Fd set for error! calling user"); | ||
1401 | fdh->references++; | ||
1402 | if (!_ecore_call_fd_cb(fdh->func, fdh->data, fdh)) | ||
1403 | { | ||
1404 | ERR("Fd function err returned 0, remove it"); | ||
1405 | if (!fdh->delete_me) | ||
1406 | { | ||
1407 | fdh->delete_me = EINA_TRUE; | ||
1408 | fd_handlers_to_delete = eina_list_append(fd_handlers_to_delete, fdh); | ||
1409 | } | ||
1410 | found++; | ||
1411 | } | ||
1412 | fdh->references--; | ||
1413 | } | ||
1414 | else | ||
1415 | { | ||
1416 | ERR("Problematic fd found at %d! setting it for delete", fdh->fd); | ||
1417 | if (!fdh->delete_me) | ||
1418 | { | ||
1419 | fdh->delete_me = EINA_TRUE; | ||
1420 | fd_handlers_to_delete = eina_list_append(fd_handlers_to_delete, fdh); | ||
1421 | } | ||
1422 | |||
1423 | found++; | ||
1424 | } | ||
1425 | } | ||
1426 | } | ||
1427 | if (found == 0) | ||
1428 | { | ||
1429 | # ifdef HAVE_GLIB | ||
1430 | ERR("No bad fd found. Maybe a foreign fd from glib?"); | ||
1431 | # else | ||
1432 | ERR("No bad fd found. EEEK!"); | ||
1433 | # endif | ||
1434 | } | ||
1435 | _ecore_main_fd_handlers_cleanup(); | ||
1436 | } | ||
1437 | |||
1438 | # endif | ||
1439 | #endif | ||
1440 | |||
1441 | static void | ||
1442 | _ecore_main_fd_handlers_cleanup(void) | ||
1443 | { | ||
1444 | Ecore_Fd_Handler *fdh; | ||
1445 | Eina_List *l, *l2; | ||
1446 | |||
1447 | if (!fd_handlers_to_delete) return; | ||
1448 | EINA_LIST_FOREACH_SAFE(fd_handlers_to_delete, l, l2, fdh) | ||
1449 | { | ||
1450 | if (!fdh) | ||
1451 | { | ||
1452 | fd_handlers_to_delete = eina_list_remove_list(l, fd_handlers_to_delete); | ||
1453 | continue; | ||
1454 | } | ||
1455 | /* fdh->delete_me should be set for all fdhs at the start of the list */ | ||
1456 | if (fdh->references) | ||
1457 | continue; | ||
1458 | if (fdh->buf_func && fd_handlers_with_buffer) | ||
1459 | fd_handlers_with_buffer = eina_list_remove(fd_handlers_with_buffer, fdh); | ||
1460 | if (fdh->prep_func && fd_handlers_with_prep) | ||
1461 | fd_handlers_with_prep = eina_list_remove(fd_handlers_with_prep, fdh); | ||
1462 | fd_handlers = (Ecore_Fd_Handler *) | ||
1463 | eina_inlist_remove(EINA_INLIST_GET(fd_handlers), EINA_INLIST_GET(fdh)); | ||
1464 | ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE); | ||
1465 | ecore_fd_handler_mp_free(fdh); | ||
1466 | fd_handlers_to_delete = eina_list_remove_list(fd_handlers_to_delete, l); | ||
1467 | } | ||
1468 | } | ||
1469 | |||
1470 | #ifdef _WIN32 | ||
1471 | static void | ||
1472 | _ecore_main_win32_handlers_cleanup(void) | ||
1473 | { | ||
1474 | Ecore_Win32_Handler *wh; | ||
1475 | Eina_Inlist *l; | ||
1476 | int deleted_in_use = 0; | ||
1477 | |||
1478 | if (!win32_handlers_delete_me) return; | ||
1479 | for (l = EINA_INLIST_GET(win32_handlers); l; ) | ||
1480 | { | ||
1481 | wh = (Ecore_Win32_Handler *)l; | ||
1482 | |||
1483 | l = l->next; | ||
1484 | if (wh->delete_me) | ||
1485 | { | ||
1486 | if (wh->references) | ||
1487 | { | ||
1488 | deleted_in_use++; | ||
1489 | continue; | ||
1490 | } | ||
1491 | |||
1492 | win32_handlers = (Ecore_Win32_Handler *) | ||
1493 | eina_inlist_remove(EINA_INLIST_GET(win32_handlers), | ||
1494 | EINA_INLIST_GET(wh)); | ||
1495 | ECORE_MAGIC_SET(wh, ECORE_MAGIC_NONE); | ||
1496 | ecore_win32_handler_mp_free(wh); | ||
1497 | } | ||
1498 | } | ||
1499 | if (!deleted_in_use) win32_handlers_delete_me = EINA_FALSE; | ||
1500 | } | ||
1501 | |||
1502 | #endif | ||
1503 | |||
1504 | static void | ||
1505 | _ecore_main_fd_handlers_call(void) | ||
1506 | { | ||
1507 | /* grab a new list */ | ||
1508 | if (!fd_handlers_to_call_current) | ||
1509 | { | ||
1510 | fd_handlers_to_call_current = fd_handlers_to_call; | ||
1511 | fd_handlers_to_call = NULL; | ||
1512 | } | ||
1513 | |||
1514 | while (fd_handlers_to_call_current) | ||
1515 | { | ||
1516 | Ecore_Fd_Handler *fdh = fd_handlers_to_call_current; | ||
1517 | |||
1518 | if (!fdh->delete_me) | ||
1519 | { | ||
1520 | if ((fdh->read_active) || | ||
1521 | (fdh->write_active) || | ||
1522 | (fdh->error_active)) | ||
1523 | { | ||
1524 | fdh->references++; | ||
1525 | if (!_ecore_call_fd_cb(fdh->func, fdh->data, fdh)) | ||
1526 | { | ||
1527 | if (!fdh->delete_me) | ||
1528 | { | ||
1529 | fdh->delete_me = EINA_TRUE; | ||
1530 | fd_handlers_to_delete = eina_list_append(fd_handlers_to_delete, fdh); | ||
1531 | } | ||
1532 | } | ||
1533 | fdh->references--; | ||
1534 | _ecore_fd_valid(); | ||
1535 | |||
1536 | fdh->read_active = EINA_FALSE; | ||
1537 | fdh->write_active = EINA_FALSE; | ||
1538 | fdh->error_active = EINA_FALSE; | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1542 | /* stop when we point to ourselves */ | ||
1543 | if (fdh->next_ready == fdh) | ||
1544 | { | ||
1545 | fdh->next_ready = NULL; | ||
1546 | fd_handlers_to_call_current = NULL; | ||
1547 | break; | ||
1548 | } | ||
1549 | |||
1550 | fd_handlers_to_call_current = fdh->next_ready; | ||
1551 | fdh->next_ready = NULL; | ||
1552 | } | ||
1553 | } | ||
1554 | |||
1555 | static int | ||
1556 | _ecore_main_fd_handlers_buf_call(void) | ||
1557 | { | ||
1558 | Ecore_Fd_Handler *fdh; | ||
1559 | Eina_List *l, *l2; | ||
1560 | int ret; | ||
1561 | |||
1562 | ret = 0; | ||
1563 | EINA_LIST_FOREACH_SAFE(fd_handlers_with_buffer, l, l2, fdh) | ||
1564 | { | ||
1565 | if (!fdh) | ||
1566 | { | ||
1567 | fd_handlers_with_buffer = eina_list_remove_list(l, fd_handlers_with_buffer); | ||
1568 | continue; | ||
1569 | } | ||
1570 | if ((!fdh->delete_me) && fdh->buf_func) | ||
1571 | { | ||
1572 | fdh->references++; | ||
1573 | if (_ecore_call_fd_cb(fdh->buf_func, fdh->buf_data, fdh)) | ||
1574 | { | ||
1575 | ret |= _ecore_call_fd_cb(fdh->func, fdh->data, fdh); | ||
1576 | fdh->read_active = EINA_TRUE; | ||
1577 | _ecore_try_add_to_call_list(fdh); | ||
1578 | } | ||
1579 | fdh->references--; | ||
1580 | } | ||
1581 | else | ||
1582 | fd_handlers_with_buffer = eina_list_remove_list(fd_handlers_with_buffer, l); | ||
1583 | } | ||
1584 | return ret; | ||
1585 | } | ||
1586 | |||
1587 | #ifndef USE_G_MAIN_LOOP | ||
1588 | |||
1589 | enum { | ||
1590 | SPIN_MORE, | ||
1591 | SPIN_RESTART, | ||
1592 | LOOP_CONTINUE | ||
1593 | }; | ||
1594 | |||
1595 | static int | ||
1596 | _ecore_main_loop_spin_core(void) | ||
1597 | { | ||
1598 | /* as we are spinning we need to update loop time per spin */ | ||
1599 | _ecore_time_loop_time = ecore_time_get(); | ||
1600 | /* call all idlers, which returns false if no more idelrs exist */ | ||
1601 | if (!_ecore_idler_all_call()) return SPIN_RESTART; | ||
1602 | /* sneaky - drop through or if checks - the first one to succeed | ||
1603 | * drops through and returns "continue" so further ones dont run */ | ||
1604 | if ((_ecore_main_select(0.0) > 0) || (_ecore_event_exist()) || | ||
1605 | (_ecore_signal_count_get() > 0) || (do_quit)) | ||
1606 | return LOOP_CONTINUE; | ||
1607 | /* default - spin more */ | ||
1608 | return SPIN_MORE; | ||
1609 | } | ||
1610 | |||
1611 | static int | ||
1612 | _ecore_main_loop_spin_no_timers(void) | ||
1613 | { | ||
1614 | /* if we have idlers we HAVE to spin and handle everything | ||
1615 | * in a polling way - spin in a tight polling loop */ | ||
1616 | for (;; ) | ||
1617 | { | ||
1618 | int action = _ecore_main_loop_spin_core(); | ||
1619 | if (action != SPIN_MORE) return action; | ||
1620 | /* if an idler has added a timer then we need to go through | ||
1621 | * the start of the spin cycle again to handle cases properly */ | ||
1622 | if (_ecore_timers_exists()) return SPIN_RESTART; | ||
1623 | } | ||
1624 | /* just contiune handling events etc. */ | ||
1625 | return LOOP_CONTINUE; | ||
1626 | } | ||
1627 | |||
1628 | static int | ||
1629 | _ecore_main_loop_spin_timers(void) | ||
1630 | { | ||
1631 | /* if we have idlers we HAVE to spin and handle everything | ||
1632 | * in a polling way - spin in a tight polling loop */ | ||
1633 | for (;; ) | ||
1634 | { | ||
1635 | int action = _ecore_main_loop_spin_core(); | ||
1636 | if (action != SPIN_MORE) return action; | ||
1637 | /* if next timer expires now or in the past - stop spinning and | ||
1638 | * continue the mainloop walk as our "select" timeout has | ||
1639 | * expired now */ | ||
1640 | if (_ecore_timer_next_get() <= 0.0) return LOOP_CONTINUE; | ||
1641 | } | ||
1642 | /* just contiune handling events etc. */ | ||
1643 | return LOOP_CONTINUE; | ||
1644 | } | ||
1645 | |||
1646 | static void | ||
1647 | _ecore_fps_marker_1(void) | ||
1648 | { | ||
1649 | if (!_ecore_fps_debug) return; | ||
1650 | t2 = ecore_time_get(); | ||
1651 | if ((t1 > 0.0) && (t2 > 0.0)) _ecore_fps_debug_runtime_add(t2 - t1); | ||
1652 | } | ||
1653 | |||
1654 | static void | ||
1655 | _ecore_fps_marker_2(void) | ||
1656 | { | ||
1657 | if (!_ecore_fps_debug) return; | ||
1658 | t1 = ecore_time_get(); | ||
1659 | } | ||
1660 | |||
1661 | static void | ||
1662 | _ecore_main_loop_iterate_internal(int once_only) | ||
1663 | { | ||
1664 | double next_time = -1.0; | ||
1665 | |||
1666 | in_main_loop++; | ||
1667 | /* expire any timers */ | ||
1668 | _ecore_timer_expired_timers_call(_ecore_time_loop_time); | ||
1669 | _ecore_timer_cleanup(); | ||
1670 | |||
1671 | /* process signals into events .... */ | ||
1672 | _ecore_signal_received_process(); | ||
1673 | /* if as a result of timers/animators or signals we have accumulated | ||
1674 | * events, then instantly handle them */ | ||
1675 | if (_ecore_event_exist()) | ||
1676 | { | ||
1677 | /* but first conceptually enter an idle state */ | ||
1678 | _ecore_idle_enterer_call(); | ||
1679 | _ecore_throttle(); | ||
1680 | /* now quickly poll to see which input fd's are active */ | ||
1681 | _ecore_main_select(0.0); | ||
1682 | /* allow newly queued timers to expire from now on */ | ||
1683 | _ecore_timer_enable_new(); | ||
1684 | /* go straight to processing the events we had queued */ | ||
1685 | goto process_all; | ||
1686 | } | ||
1687 | |||
1688 | if (once_only) | ||
1689 | { | ||
1690 | /* in once_only mode we should quickly poll for inputs, signals | ||
1691 | * if we got any events or signals, allow new timers to process. | ||
1692 | * use bitwise or to force both conditions to be tested and | ||
1693 | * merged together */ | ||
1694 | if (_ecore_main_select(0.0) | _ecore_signal_count_get()) | ||
1695 | { | ||
1696 | _ecore_timer_enable_new(); | ||
1697 | goto process_all; | ||
1698 | } | ||
1699 | } | ||
1700 | else | ||
1701 | { | ||
1702 | /* call idle enterers ... */ | ||
1703 | _ecore_idle_enterer_call(); | ||
1704 | _ecore_throttle(); | ||
1705 | } | ||
1706 | |||
1707 | /* if these calls caused any buffered events to appear - deal with them */ | ||
1708 | if (fd_handlers_with_buffer) | ||
1709 | _ecore_main_fd_handlers_buf_call(); | ||
1710 | |||
1711 | /* if there are any (buffered fd handling may generate them) | ||
1712 | * then jump to processing them */ | ||
1713 | if (_ecore_event_exist()) | ||
1714 | { | ||
1715 | _ecore_main_select(0.0); | ||
1716 | _ecore_timer_enable_new(); | ||
1717 | goto process_all; | ||
1718 | } | ||
1719 | |||
1720 | if (once_only) | ||
1721 | { | ||
1722 | /* in once_only mode enter idle here instead and then return */ | ||
1723 | _ecore_idle_enterer_call(); | ||
1724 | _ecore_throttle(); | ||
1725 | _ecore_timer_enable_new(); | ||
1726 | goto done; | ||
1727 | } | ||
1728 | |||
1729 | _ecore_fps_marker_1(); | ||
1730 | |||
1731 | /* start of the sleeping or looping section */ | ||
1732 | start_loop: /***************************************************************/ | ||
1733 | /* any timers re-added as a result of these are allowed to go */ | ||
1734 | _ecore_timer_enable_new(); | ||
1735 | /* if we have been asked to quit the mainloop then exit at this point */ | ||
1736 | if (do_quit) | ||
1737 | { | ||
1738 | _ecore_timer_enable_new(); | ||
1739 | goto done; | ||
1740 | } | ||
1741 | if (!_ecore_event_exist()) | ||
1742 | { | ||
1743 | /* init flags */ | ||
1744 | next_time = _ecore_timer_next_get(); | ||
1745 | /* no idlers */ | ||
1746 | if (!_ecore_idler_exist()) | ||
1747 | { | ||
1748 | /* sleep until timeout or forever (-1.0) waiting for on fds */ | ||
1749 | _ecore_main_select(next_time); | ||
1750 | } | ||
1751 | else | ||
1752 | { | ||
1753 | int action = LOOP_CONTINUE; | ||
1754 | |||
1755 | /* no timers - spin */ | ||
1756 | if (next_time < 0) action = _ecore_main_loop_spin_no_timers(); | ||
1757 | /* timers - spin */ | ||
1758 | else action = _ecore_main_loop_spin_timers(); | ||
1759 | if (action == SPIN_RESTART) goto start_loop; | ||
1760 | } | ||
1761 | } | ||
1762 | _ecore_fps_marker_2(); | ||
1763 | |||
1764 | /* actually wake up and deal with input, events etc. */ | ||
1765 | process_all: /***********************************************************/ | ||
1766 | |||
1767 | /* we came out of our "wait state" so idle has exited */ | ||
1768 | if (!once_only) _ecore_idle_exiter_call(); | ||
1769 | /* call the fd handler per fd that became alive... */ | ||
1770 | /* this should read or write any data to the monitored fd and then */ | ||
1771 | /* post events onto the ecore event pipe if necessary */ | ||
1772 | _ecore_main_fd_handlers_call(); | ||
1773 | if (fd_handlers_with_buffer) _ecore_main_fd_handlers_buf_call(); | ||
1774 | /* process signals into events .... */ | ||
1775 | _ecore_signal_received_process(); | ||
1776 | /* handle events ... */ | ||
1777 | _ecore_event_call(); | ||
1778 | _ecore_main_fd_handlers_cleanup(); | ||
1779 | |||
1780 | if (once_only) | ||
1781 | { | ||
1782 | /* if in once_only mode handle idle exiting */ | ||
1783 | _ecore_idle_enterer_call(); | ||
1784 | _ecore_throttle(); | ||
1785 | } | ||
1786 | |||
1787 | done: /*******************************************************************/ | ||
1788 | in_main_loop--; | ||
1789 | } | ||
1790 | |||
1791 | #endif | ||
1792 | |||
1793 | #ifdef _WIN32 | ||
1794 | static int | ||
1795 | _ecore_main_win32_select(int nfds __UNUSED__, | ||
1796 | fd_set *readfds, | ||
1797 | fd_set *writefds, | ||
1798 | fd_set *exceptfds, | ||
1799 | struct timeval *tv) | ||
1800 | { | ||
1801 | HANDLE objects[MAXIMUM_WAIT_OBJECTS]; | ||
1802 | int sockets[MAXIMUM_WAIT_OBJECTS]; | ||
1803 | Ecore_Fd_Handler *fdh; | ||
1804 | Ecore_Win32_Handler *wh; | ||
1805 | unsigned int objects_nbr = 0; | ||
1806 | unsigned int handles_nbr = 0; | ||
1807 | unsigned int events_nbr = 0; | ||
1808 | DWORD result; | ||
1809 | DWORD timeout; | ||
1810 | MSG msg; | ||
1811 | unsigned int i; | ||
1812 | int res; | ||
1813 | |||
1814 | /* Create an event object per socket */ | ||
1815 | EINA_INLIST_FOREACH(fd_handlers, fdh) | ||
1816 | { | ||
1817 | WSAEVENT event; | ||
1818 | long network_event; | ||
1819 | |||
1820 | network_event = 0; | ||
1821 | if (FD_ISSET(fdh->fd, readfds)) | ||
1822 | network_event |= FD_READ; | ||
1823 | if (FD_ISSET(fdh->fd, writefds)) | ||
1824 | network_event |= FD_WRITE; | ||
1825 | if (FD_ISSET(fdh->fd, exceptfds)) | ||
1826 | network_event |= FD_OOB; | ||
1827 | |||
1828 | if (network_event) | ||
1829 | { | ||
1830 | event = WSACreateEvent(); | ||
1831 | WSAEventSelect(fdh->fd, event, network_event); | ||
1832 | objects[objects_nbr] = event; | ||
1833 | sockets[events_nbr] = fdh->fd; | ||
1834 | events_nbr++; | ||
1835 | objects_nbr++; | ||
1836 | } | ||
1837 | } | ||
1838 | |||
1839 | /* store the HANDLEs in the objects to wait for */ | ||
1840 | EINA_INLIST_FOREACH(win32_handlers, wh) | ||
1841 | { | ||
1842 | objects[objects_nbr] = wh->h; | ||
1843 | handles_nbr++; | ||
1844 | objects_nbr++; | ||
1845 | } | ||
1846 | |||
1847 | /* Empty the queue before waiting */ | ||
1848 | while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) | ||
1849 | { | ||
1850 | TranslateMessage(&msg); | ||
1851 | DispatchMessage(&msg); | ||
1852 | } | ||
1853 | |||
1854 | /* Wait for any message sent or posted to this queue */ | ||
1855 | /* or for one of the passed handles be set to signaled. */ | ||
1856 | if (!tv) | ||
1857 | timeout = INFINITE; | ||
1858 | else | ||
1859 | timeout = (DWORD)((tv->tv_sec * 1000.0) + (tv->tv_usec / 1000.0)); | ||
1860 | |||
1861 | if (timeout == 0) return 0; | ||
1862 | |||
1863 | result = MsgWaitForMultipleObjects(objects_nbr, (const HANDLE *)objects, EINA_FALSE, | ||
1864 | timeout, QS_ALLINPUT); | ||
1865 | |||
1866 | FD_ZERO(readfds); | ||
1867 | FD_ZERO(writefds); | ||
1868 | FD_ZERO(exceptfds); | ||
1869 | |||
1870 | /* The result tells us the type of event we have. */ | ||
1871 | if (result == WAIT_FAILED) | ||
1872 | { | ||
1873 | char *m; | ||
1874 | |||
1875 | m = evil_last_error_get(); | ||
1876 | ERR(" * %s\n", m); | ||
1877 | free(m); | ||
1878 | res = -1; | ||
1879 | } | ||
1880 | else if (result == WAIT_TIMEOUT) | ||
1881 | { | ||
1882 | /* ERR("time out\n"); */ | ||
1883 | res = 0; | ||
1884 | } | ||
1885 | else if (result == (WAIT_OBJECT_0 + objects_nbr)) | ||
1886 | { | ||
1887 | while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) | ||
1888 | { | ||
1889 | TranslateMessage(&msg); | ||
1890 | DispatchMessage(&msg); | ||
1891 | } | ||
1892 | |||
1893 | res = 0; | ||
1894 | } | ||
1895 | else if ((result >= 0) && (result < WAIT_OBJECT_0 + events_nbr)) | ||
1896 | { | ||
1897 | WSANETWORKEVENTS network_event; | ||
1898 | |||
1899 | WSAEnumNetworkEvents(sockets[result], objects[result], &network_event); | ||
1900 | |||
1901 | if (network_event.lNetworkEvents & FD_READ) | ||
1902 | FD_SET(sockets[result], readfds); | ||
1903 | if (network_event.lNetworkEvents & FD_WRITE) | ||
1904 | FD_SET(sockets[result], writefds); | ||
1905 | if (network_event.lNetworkEvents & FD_OOB) | ||
1906 | FD_SET(sockets[result], exceptfds); | ||
1907 | |||
1908 | res = 1; | ||
1909 | } | ||
1910 | else if ((result >= (WAIT_OBJECT_0 + events_nbr)) && | ||
1911 | (result < (WAIT_OBJECT_0 + objects_nbr))) | ||
1912 | { | ||
1913 | if (!win32_handler_current) | ||
1914 | { | ||
1915 | /* regular main loop, start from head */ | ||
1916 | win32_handler_current = win32_handlers; | ||
1917 | } | ||
1918 | else | ||
1919 | { | ||
1920 | /* recursive main loop, continue from where we were */ | ||
1921 | win32_handler_current = (Ecore_Win32_Handler *)EINA_INLIST_GET(win32_handler_current)->next; | ||
1922 | } | ||
1923 | |||
1924 | while (win32_handler_current) | ||
1925 | { | ||
1926 | wh = win32_handler_current; | ||
1927 | |||
1928 | if (objects[result - WAIT_OBJECT_0] == wh->h) | ||
1929 | { | ||
1930 | if (!wh->delete_me) | ||
1931 | { | ||
1932 | wh->references++; | ||
1933 | if (!wh->func(wh->data, wh)) | ||
1934 | { | ||
1935 | wh->delete_me = EINA_TRUE; | ||
1936 | win32_handlers_delete_me = EINA_TRUE; | ||
1937 | } | ||
1938 | wh->references--; | ||
1939 | } | ||
1940 | } | ||
1941 | if (win32_handler_current) /* may have changed in recursive main loops */ | ||
1942 | win32_handler_current = (Ecore_Win32_Handler *)EINA_INLIST_GET(win32_handler_current)->next; | ||
1943 | } | ||
1944 | res = 1; | ||
1945 | } | ||
1946 | else | ||
1947 | { | ||
1948 | ERR("unknown result...\n"); | ||
1949 | res = -1; | ||
1950 | } | ||
1951 | |||
1952 | /* Remove event objects again */ | ||
1953 | for (i = 0; i < events_nbr; i++) WSACloseEvent(objects[i]); | ||
1954 | |||
1955 | return res; | ||
1956 | } | ||
1957 | |||
1958 | #endif | ||