1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #define EINA_SLSTR_INTERNAL
6
7 #define FD_SETSIZE 8192
8
9 #ifdef _WIN32
10 # ifndef USER_TIMER_MINIMUM
11 # define USER_TIMER_MINIMUM 0x0a
12 # endif
13 #endif
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <math.h>
20 #include <sys/types.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <sys/time.h>
24
25 #ifdef HAVE_IEEEFP_H
26 # include <ieeefp.h> // for Solaris
27 #endif
28
29 #ifdef HAVE_ISFINITE
30 # define ECORE_FINITE(t) isfinite(t)
31 #else
32 # define ECORE_FINITE(t) finite(t)
33 #endif
34
35 //#define FIX_HZ 1
36
37 #ifdef FIX_HZ
38 # include <sys/param.h>
39 # ifndef HZ
40 # define HZ 100
41 # endif
42 #endif
43
44 #ifdef _WIN32
45 # include <evil_private.h> /* evil_last_error_get */
46 #endif
47 #include "Ecore.h"
48 #include "ecore_private.h"
49
50 #include "ecore_main_common.h"
51
52 #include "eina_internal.h"
53
54 #ifdef USE_G_MAIN_LOOP
55 # include <glib.h>
56 #endif
57
58 #ifdef HAVE_LIBUV
59 # ifdef HAVE_NODE_UV_H
60 # include <node/uv.h>
61 # elif defined(HAVE_NODEJS_DEPS_UV_UV_H)
62 # include <nodejs/deps/uv/uv.h>
63 # elif defined(HAVE_NODEJS_DEPS_UV_INCLUDE_UV_H)
64 # include <nodejs/deps/uv/include/uv.h>
65 # elif defined(HAVE_NODEJS_SRC_UV_H)
66 # include <nodejs/src/uv.h>
67 # elif defined(HAVE_UV_H)
68 # include <uv.h>
69 # else
70 # error No uv.h header found?
71 # endif
72
73 // XXX: FIXME: use eina_module
74 # if defined(HAVE_DLOPEN) && !defined(_WIN32)
75 # include <dlfcn.h>
76 # endif
77
78 static uv_prepare_t _ecore_main_uv_prepare;
79 static uv_check_t _ecore_main_uv_check;
80 static uv_timer_t _ecore_main_uv_handle_timers;
81 static Eina_Bool _ecore_main_uv_idling;
82
83 static int (*_dl_uv_loop_alive)(uv_loop_t*) = 0;
84 static int (*_dl_uv_run)(uv_loop_t*, uv_run_mode mode) = 0;
85 static int (*_dl_uv_stop)(uv_loop_t*) = 0;
86 static uv_loop_t* (*_dl_uv_default_loop)() = 0;
87 static int (*_dl_uv_poll_init_socket)(uv_loop_t* loop, uv_poll_t* handle, uv_os_sock_t fd) = 0;
88 static int (*_dl_uv_poll_init)(uv_loop_t* loop, uv_poll_t* handle, int fd) = 0;
89 static int (*_dl_uv_poll_start)(uv_poll_t* handle, int events, uv_poll_cb cb) = 0;
90 static int (*_dl_uv_poll_stop)(uv_poll_t* handle) = 0;
91 static int (*_dl_uv_timer_init)(uv_loop_t*, uv_timer_t* handle);
92 static int (*_dl_uv_timer_start)(uv_timer_t* handle,
93 uv_timer_cb cb,
94 uint64_t timeout,
95 uint64_t repeat);
96 static int (*_dl_uv_timer_stop)(uv_timer_t* handle);
97 static int (*_dl_uv_prepare_init)(uv_loop_t*, uv_prepare_t* prepare);
98 static int (*_dl_uv_prepare_start)(uv_prepare_t* prepare, uv_prepare_cb cb);
99 static int (*_dl_uv_prepare_stop)(uv_prepare_t* prepare);
100 static int (*_dl_uv_check_init)(uv_loop_t*, uv_check_t* prepare);
101 static int (*_dl_uv_check_start)(uv_check_t* prepare, uv_check_cb cb);
102 static int (*_dl_uv_check_stop)(uv_check_t* prepare);
103 static int (*_dl_uv_close)(uv_handle_t* handle, uv_close_cb close_cb);
104 #endif
105
106 #define NS_PER_SEC (1000000000.0)
107
108 struct _Ecore_Fd_Handler
109 {
110 EINA_INLIST;
111 ECORE_MAGIC;
112 Ecore_Fd_Handler *next_ready;
113 int fd;
114 Ecore_Fd_Handler_Flags flags;
115 Eo *handler;
116 Eo *loop;
117 Efl_Loop_Data *loop_data;
118 Ecore_Fd_Cb func;
119 void *data;
120 Ecore_Fd_Cb buf_func;
121 void *buf_data;
122 Ecore_Fd_Prep_Cb prep_func;
123 void *prep_data;
124 int references;
125 #if defined(USE_G_MAIN_LOOP)
126 GPollFD gfd;
127 #endif
128 #ifdef HAVE_LIBUV
129 uv_poll_t uv_handle;
130 #endif
131 Eina_Bool read_active : 1;
132 Eina_Bool write_active : 1;
133 Eina_Bool error_active : 1;
134 Eina_Bool delete_me : 1;
135 Eina_Bool file : 1;
136 Eina_Bool legacy : 1;
137 };
138 GENERIC_ALLOC_SIZE_DECLARE(Ecore_Fd_Handler);
139
140 #ifdef _WIN32
141 struct _Ecore_Win32_Handler
142 {
143 EINA_INLIST;
144 ECORE_MAGIC;
145 HANDLE h;
146 Eo *handler;
147 Eo *loop;
148 Efl_Loop_Data *loop_data;
149 Ecore_Win32_Handle_Cb func;
150 void *data;
151 int references;
152 Eina_Bool delete_me : 1;
153 };
154 GENERIC_ALLOC_SIZE_DECLARE(Ecore_Win32_Handler);
155 #endif
156
157 #if !defined(USE_G_MAIN_LOOP) && !defined(HAVE_LIBUV)
158 static int _ecore_main_select(Eo *obj, Efl_Loop_Data *pd, double timeout);
159 #endif
160 static void _ecore_main_prepare_handlers(Eo *obj, Efl_Loop_Data *pd);
161 static void _ecore_main_fd_handlers_cleanup(Eo *obj, Efl_Loop_Data *pd);
162 #ifndef _WIN32
163 # ifndef USE_G_MAIN_LOOP
164 static void _ecore_main_fd_handlers_bads_rem(Eo *obj, Efl_Loop_Data *pd);
165 # endif
166 #endif
167 static void _ecore_main_fd_handlers_call(Eo *obj, Efl_Loop_Data *pd);
168 static int _ecore_main_fd_handlers_buf_call(Eo *obj, Efl_Loop_Data *pd);
169 #ifndef USE_G_MAIN_LOOP
170 static void _ecore_main_loop_iterate_internal(Eo *obj, Efl_Loop_Data *pd, int once_only);
171 #endif
172
173 #ifdef _WIN32
174 static int _ecore_main_win32_select(int nfds,
175 fd_set *readfds,
176 fd_set *writefds,
177 fd_set *exceptfds,
178 struct timeval *timeout);
179 static void _ecore_main_win32_handlers_cleanup(Eo *obj, Efl_Loop_Data *pd);
180 #endif
181
182 static void _ecore_main_loop_setup(Eo *obj, Efl_Loop_Data *pd);
183 static void _ecore_main_loop_clear(Eo *obj, Efl_Loop_Data *pd);
184
185 // for legacy mainloop only and not other loops
186 int in_main_loop = 0;
187 #ifndef USE_G_MAIN_LOOP
188 static double t1 = 0.0;
189 static double t2 = 0.0;
190 #endif
191
192 #ifdef _WIN32
193 Ecore_Select_Function main_loop_select = _ecore_main_win32_select;
194 static Ecore_Select_Function general_loop_select = _ecore_main_win32_select;
195 #else
196 # include <sys/select.h>
197 Ecore_Select_Function main_loop_select = select;
198 static Ecore_Select_Function general_loop_select = select;
199 #endif
200
201 #ifdef USE_G_MAIN_LOOP
202 static GPollFD ecore_epoll_fd;
203 static GPollFD ecore_timer_fd;
204 static GSource *ecore_glib_source;
205 static guint ecore_glib_source_id;
206 static GMainLoop *ecore_main_loop;
207 static gboolean ecore_idling;
208 static gboolean _ecore_glib_idle_enterer_called;
209 static gboolean ecore_fds_ready;
210 #endif
211
212 static double _ecore_main_loop_wakeup_time = 0.0;
213
_ecore_main_loop_wakeup_time_get(void)214 EAPI double _ecore_main_loop_wakeup_time_get(void)
215 {
216 return _ecore_main_loop_wakeup_time;
217 }
218
219 static inline void
_update_loop_time(Efl_Loop_Data * pd)220 _update_loop_time(Efl_Loop_Data *pd)
221 {
222 double loop_time = ecore_time_get();
223 if (loop_time > pd->loop_time)
224 pd->loop_time = loop_time;
225 _ecore_main_loop_wakeup_time = loop_time;
226 }
227
228 #ifdef EFL_EXTRA_SANITY_CHECKS
229 static inline void
_ecore_fd_valid(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd EINA_UNUSED)230 _ecore_fd_valid(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
231 {
232 # ifdef HAVE_SYS_EPOLL_H
233 if ((pd->epoll_fd >= 0) &&
234 (fcntl(pd->epoll_fd, F_GETFD) < 0))
235 {
236 ERR("arghhh you caught me! report a backtrace to edevel!");
237 # ifdef HAVE_PAUSE
238 pause();
239 # else
240 sleep(60);
241 # endif
242 }
243 # endif
244 }
245 #endif
246
247 static inline void
_ecore_try_add_to_call_list(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd,Ecore_Fd_Handler * fdh)248 _ecore_try_add_to_call_list(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, Ecore_Fd_Handler *fdh)
249 {
250 // check if this fdh is already in the list
251 if (fdh->next_ready)
252 {
253 DBG("next_ready");
254 return;
255 }
256 if (fdh->read_active || fdh->write_active || fdh->error_active || (fdh->flags & ECORE_FD_ALWAYS))
257 {
258 DBG("added");
259 // make sure next_ready is non-null by pointing to ourselves
260 // use that to indicate this fdh is in the ready list
261 // insert at the head of the list to avoid trouble
262 fdh->next_ready = pd->fd_handlers_to_call ? pd->fd_handlers_to_call : fdh;
263 pd->fd_handlers_to_call = fdh;
264 }
265 }
266
267 static inline void
_throttle_do(Efl_Loop_Data * pd)268 _throttle_do(Efl_Loop_Data *pd)
269 {
270 if (pd->throttle == 0) return;
271 eina_evlog("+throttle", NULL, 0.0, NULL);
272 usleep(pd->throttle);
273 eina_evlog("-throttle", NULL, 0.0, NULL);
274 }
275
276 #ifdef HAVE_SYS_EPOLL_H
277 static inline int
_ecore_get_epoll_fd(Eo * obj,Efl_Loop_Data * pd)278 _ecore_get_epoll_fd(Eo *obj, Efl_Loop_Data *pd)
279 {
280 if (pd->epoll_pid && (pd->epoll_pid != getpid())) // forked!
281 _ecore_main_loop_clear(obj, pd);
282 if ((pd->epoll_pid == 0) && (pd->epoll_fd < 0))
283 _ecore_main_loop_setup(obj, pd);
284 return pd->epoll_fd;
285 }
286
287 static inline int
_ecore_epoll_add(int efd,int fd,int events,void * ptr)288 _ecore_epoll_add(int efd,
289 int fd,
290 int events,
291 void *ptr)
292 {
293 struct epoll_event ev;
294
295 memset(&ev, 0, sizeof (ev));
296 ev.events = events;
297 ev.data.ptr = ptr;
298 DBG("adding poll on %d %08x", fd, events);
299 return epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev);
300 }
301
302 static inline int
_ecore_poll_events_from_fdh(Ecore_Fd_Handler * fdh)303 _ecore_poll_events_from_fdh(Ecore_Fd_Handler *fdh)
304 {
305 int events = 0;
306 if (fdh->flags & ECORE_FD_READ) events |= EPOLLIN | EPOLLHUP;
307 if (fdh->flags & ECORE_FD_WRITE) events |= EPOLLOUT | EPOLLHUP;
308 if (fdh->flags & ECORE_FD_ERROR) events |= EPOLLERR | EPOLLPRI | EPOLLHUP;
309 return events;
310 }
311 #endif
312
313 #ifdef USE_G_MAIN_LOOP
314 static inline int
_gfd_events_from_fdh(Ecore_Fd_Handler * fdh)315 _gfd_events_from_fdh(Ecore_Fd_Handler *fdh)
316 {
317 int events = 0;
318 if (fdh->flags & ECORE_FD_READ) events |= G_IO_IN | G_IO_HUP;
319 if (fdh->flags & ECORE_FD_WRITE) events |= G_IO_OUT | G_IO_HUP;
320 if (fdh->flags & ECORE_FD_ERROR) events |= G_IO_ERR | G_IO_HUP;
321 return events;
322 }
323 #endif
324
325
326 static void
_ecore_main_pre_idle_exit(void)327 _ecore_main_pre_idle_exit(void)
328 {
329 // even if we never go idle, keep up flushing some of our freeq away
330 // on every idle exit which may happen if we even never called idlers
331 // for now an idea but dont enforce
332 // eina_freeq_reduce(eina_freeq_main_get(), 128);
333 }
334
335 #ifdef HAVE_LIBUV
336 static void
_ecore_main_uv_poll_cb(uv_poll_t * handle,int status,int events)337 _ecore_main_uv_poll_cb(uv_poll_t *handle, int status, int events)
338 {
339 Eo *obj = ML_OBJ;
340 Efl_Loop_Data *pd = ML_DAT;
341
342 DBG("_ecore_main_uv_poll_cb %p status %d events %d",
343 (void *)handle->data, status, events);
344 Ecore_Fd_Handler *fdh = handle->data;
345
346 if (_ecore_main_uv_idling)
347 {
348 DBG("not IDLE anymore");
349 _ecore_main_uv_idling = EINA_FALSE;
350 eina_file_statgen_next();
351 _ecore_main_pre_idle_exit();
352 efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
353 _ecore_animator_run_reset();
354 }
355
356 if (status) fdh->error_active = EINA_TRUE;
357 if (events & UV_READABLE) fdh->read_active = EINA_TRUE;
358 if (events & UV_WRITABLE) fdh->write_active = EINA_TRUE;
359
360 if (events & UV_DISCONNECT)
361 {
362 fdh->read_active = EINA_TRUE;
363 fdh->write_active = EINA_TRUE;
364 fdh->error_active = EINA_TRUE;
365 }
366 _ecore_try_add_to_call_list(obj, pd, fdh);
367
368 _ecore_main_fd_handlers_call(obj, pd);
369 if (pd->fd_handlers_with_buffer) _ecore_main_fd_handlers_buf_call(obj, pd);
370 _ecore_signal_received_process(obj, pd);
371 efl_loop_message_process(obj);
372 _ecore_main_fd_handlers_cleanup(obj, pd);
373 _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time);
374 }
375
376 static int
_ecore_main_uv_events_from_fdh(Ecore_Fd_Handler * fdh)377 _ecore_main_uv_events_from_fdh(Ecore_Fd_Handler *fdh)
378 {
379 int events = 0;
380 if (fdh->flags & ECORE_FD_READ) events |= UV_READABLE;
381 if (fdh->flags & ECORE_FD_WRITE) events |= UV_WRITABLE;
382 DBG("events is %d", (int)events);
383 return events;
384 }
385 #endif
386
387 static inline int
_ecore_main_fdh_poll_add(Efl_Loop_Data * pd EINA_UNUSED,Ecore_Fd_Handler * fdh)388 _ecore_main_fdh_poll_add(Efl_Loop_Data *pd EINA_UNUSED, Ecore_Fd_Handler *fdh)
389 {
390 DBG("_ecore_main_fdh_poll_add");
391 int r = 0;
392
393 #ifdef HAVE_SYS_EPOLL_H
394 # ifdef HAVE_LIBUV
395 if (!_dl_uv_run)
396 # endif
397 {
398 if ((!fdh->file) && (pd->epoll_fd >= 0))
399 r = _ecore_epoll_add(_ecore_get_epoll_fd(fdh->loop, pd), fdh->fd,
400 _ecore_poll_events_from_fdh(fdh), fdh);
401 }
402 # ifdef HAVE_LIBUV
403 else
404 # endif
405 #endif
406 {
407 #ifdef HAVE_LIBUV
408 if (!fdh->file)
409 {
410 DBG("_ecore_main_fdh_poll_add libuv socket %p", fdh);
411 fdh->uv_handle.data = fdh;
412 DBG("_ecore_main_fdh_poll_add2 %p", fdh);
413 _dl_uv_poll_init_socket(_dl_uv_default_loop(),
414 &fdh->uv_handle, fdh->fd);
415 DBG("_ecore_main_fdh_poll_add3 %p", fdh->uv_handle.data);
416 _dl_uv_poll_start(&fdh->uv_handle,
417 _ecore_main_uv_events_from_fdh(fdh)
418 , _ecore_main_uv_poll_cb);
419 DBG("_ecore_main_fdh_poll_add libuv DONE");
420 }
421 else
422 {
423 DBG("_ecore_main_fdh_poll_add libuv file");
424 fdh->uv_handle.data = fdh;
425 DBG("_ecore_main_fdh_poll_add2 %p", fdh);
426 _dl_uv_poll_init(_dl_uv_default_loop(),
427 &fdh->uv_handle, fdh->fd);
428 DBG("_ecore_main_fdh_poll_add3 %p", fdh->uv_handle.data);
429 _dl_uv_poll_start(&fdh->uv_handle,
430 _ecore_main_uv_events_from_fdh(fdh)
431 , _ecore_main_uv_poll_cb);
432 DBG("_ecore_main_fdh_poll_add libuv DONE");
433 }
434 #elif defined(USE_G_MAIN_LOOP)
435 fdh->gfd.fd = fdh->fd;
436 fdh->gfd.events = _gfd_events_from_fdh(fdh);
437 fdh->gfd.revents = 0;
438 DBG("adding gpoll on %d %08x", fdh->fd, fdh->gfd.events);
439 g_source_add_poll(ecore_glib_source, &fdh->gfd);
440 #endif
441 }
442 return r;
443 }
444
445 static inline void
_ecore_main_fdh_poll_del(Efl_Loop_Data * pd,Ecore_Fd_Handler * fdh)446 _ecore_main_fdh_poll_del(Efl_Loop_Data *pd, Ecore_Fd_Handler *fdh)
447 {
448 #ifdef HAVE_SYS_EPOLL_H
449 # ifdef HAVE_LIBUV
450 if (!_dl_uv_run)
451 # endif
452 {
453 if (!pd)
454 {
455 WRN("Efl_Loop_Data is NULL!");
456 return;
457 }
458
459 if ((!fdh->file) && (pd->epoll_fd >= 0))
460 {
461 struct epoll_event ev;
462 int efd = _ecore_get_epoll_fd(fdh->loop, pd);
463
464 memset(&ev, 0, sizeof (ev));
465 DBG("removing poll on %d", fdh->fd);
466 // could get an EBADF if somebody closed the FD before removing
467 if ((epoll_ctl(efd, EPOLL_CTL_DEL, fdh->fd, &ev) < 0))
468 {
469 if (errno == EBADF)
470 {
471 WRN("fd %d closed, can't remove from epoll - reinit!",
472 fdh->fd);
473 _ecore_main_loop_clear(fdh->loop, pd);
474 _ecore_main_loop_setup(fdh->loop, pd);
475 }
476 else ERR("Failed to delete epoll fd %d! (errno=%d)",
477 fdh->fd, errno);
478 }
479 }
480 }
481 # ifdef HAVE_LIBUV
482 else
483 # endif
484 #endif
485 {
486 #ifdef HAVE_LIBUV
487 DBG("_ecore_main_fdh_poll_del libuv %p", fdh);
488 uv_handle_t* h = (uv_handle_t*)&fdh->uv_handle;
489 _dl_uv_close(h, 0);
490 DBG("_ecore_main_fdh_poll_del libuv DONE");
491 #elif USE_G_MAIN_LOOP
492 fdh->gfd.fd = fdh->fd;
493 fdh->gfd.events = _gfd_events_from_fdh(fdh);
494 fdh->gfd.revents = 0;
495 DBG("removing gpoll on %d %08x", fdh->fd, fdh->gfd.events);
496 g_source_remove_poll(ecore_glib_source, &fdh->gfd);
497 #endif
498 }
499 }
500
501 static inline int
_ecore_main_fdh_poll_modify(Efl_Loop_Data * pd EINA_UNUSED,Ecore_Fd_Handler * fdh)502 _ecore_main_fdh_poll_modify(Efl_Loop_Data *pd EINA_UNUSED, Ecore_Fd_Handler *fdh)
503 {
504 DBG("_ecore_main_fdh_poll_modify %p", fdh);
505 int r = 0;
506 #ifdef HAVE_SYS_EPOLL_H
507 # ifdef HAVE_LIBUV
508 if (!_dl_uv_run)
509 # endif
510 {
511 if ((!fdh->file) && (pd->epoll_fd >= 0))
512 {
513 struct epoll_event ev;
514 int efd = _ecore_get_epoll_fd(fdh->loop, pd);
515
516 memset(&ev, 0, sizeof (ev));
517 ev.events = _ecore_poll_events_from_fdh(fdh);
518 ev.data.ptr = fdh;
519 DBG("modifing epoll on %d to %08x", fdh->fd, ev.events);
520 r = epoll_ctl(efd, EPOLL_CTL_MOD, fdh->fd, &ev);
521 }
522 }
523 # ifdef HAVE_LIBUV
524 else
525 # endif
526 #endif
527 {
528 #ifdef HAVE_LIBUV
529 _dl_uv_poll_start(&fdh->uv_handle, _ecore_main_uv_events_from_fdh(fdh)
530 , _ecore_main_uv_poll_cb);
531 #elif defined(USE_G_MAIN_LOOP)
532 fdh->gfd.fd = fdh->fd;
533 fdh->gfd.events = _gfd_events_from_fdh(fdh);
534 fdh->gfd.revents = 0;
535 DBG("modifing gpoll on %d to %08x", fdh->fd, fdh->gfd.events);
536 #endif
537 }
538 return r;
539 }
540
541 static Eina_Bool
_ecore_main_idlers_exist(Efl_Loop_Data * pd)542 _ecore_main_idlers_exist(Efl_Loop_Data *pd)
543 {
544 return pd->idlers || eina_freeq_ptr_pending(eina_freeq_main_get());
545 }
546
547 static void
_ecore_main_idler_all_call(Eo * loop,Efl_Loop_Data * pd)548 _ecore_main_idler_all_call(Eo *loop, Efl_Loop_Data *pd)
549 {
550 if (pd->idlers)
551 efl_event_callback_call(loop, EFL_LOOP_EVENT_IDLE, NULL);
552 eina_freeq_reduce(eina_freeq_main_get(), 256);
553 }
554
555 #ifdef HAVE_SYS_EPOLL_H
556 static inline int
_ecore_main_fdh_epoll_mark_active(Eo * obj,Efl_Loop_Data * pd)557 _ecore_main_fdh_epoll_mark_active(Eo *obj, Efl_Loop_Data *pd)
558 {
559 DBG("_ecore_main_fdh_epoll_mark_active");
560 struct epoll_event ev[32];
561 int i, ret;
562 int efd = _ecore_get_epoll_fd(obj, pd);
563
564 memset(&ev, 0, sizeof (ev));
565 ret = epoll_wait(efd, ev, sizeof(ev) / sizeof(struct epoll_event), 0);
566 if (ret < 0)
567 {
568 if (errno == EINTR) return -1;
569 ERR("epoll_wait failed on fd: %d %s", efd, strerror(errno));
570 return -1;
571 }
572
573 for (i = 0; i < ret; i++)
574 {
575 Ecore_Fd_Handler *fdh;
576
577 fdh = ev[i].data.ptr;
578 if (!ECORE_MAGIC_CHECK(fdh, ECORE_MAGIC_FD_HANDLER))
579 {
580 ECORE_MAGIC_FAIL(fdh, ECORE_MAGIC_FD_HANDLER,
581 "_ecore_main_fdh_epoll_mark_active");
582 continue;
583 }
584 if (fdh->delete_me)
585 {
586 ERR("deleted fd in epoll");
587 continue;
588 }
589
590 if (ev[i].events & EPOLLIN) fdh->read_active = EINA_TRUE;
591 if (ev[i].events & EPOLLOUT) fdh->write_active = EINA_TRUE;
592 if (ev[i].events & EPOLLERR) fdh->error_active = EINA_TRUE;
593
594 if (ev[i].events & EPOLLHUP)
595 {
596 fdh->read_active = EINA_TRUE;
597 fdh->write_active = EINA_TRUE;
598 fdh->error_active = EINA_TRUE;
599 }
600 /* We'll add this one anyway outside this function,
601 don't want it twice */
602 if (fdh->flags & ECORE_FD_ALWAYS)
603 continue;
604
605 _ecore_try_add_to_call_list(obj, pd, fdh);
606 }
607 return ret;
608 }
609 #endif
610
611 #ifdef USE_G_MAIN_LOOP
612 static inline int
_ecore_main_fdh_glib_mark_active(Eo * obj,Efl_Loop_Data * pd)613 _ecore_main_fdh_glib_mark_active(Eo *obj, Efl_Loop_Data *pd)
614 {
615 Ecore_Fd_Handler *fdh;
616 int ret = 0;
617
618 // call the prepare callback for all handlers
619 EINA_INLIST_FOREACH(pd->fd_handlers, fdh)
620 {
621 if (fdh->delete_me) continue;
622
623 if (fdh->gfd.revents & G_IO_IN) fdh->read_active = EINA_TRUE;
624 if (fdh->gfd.revents & G_IO_OUT) fdh->write_active = EINA_TRUE;
625 if (fdh->gfd.revents & G_IO_ERR) fdh->error_active = EINA_TRUE;
626
627 if (fdh->gfd.revents & G_IO_HUP)
628 {
629 fdh->read_active = EINA_TRUE;
630 fdh->write_active = EINA_TRUE;
631 fdh->error_active = EINA_TRUE;
632 }
633
634 _ecore_try_add_to_call_list(obj, pd, fdh);
635
636 if (fdh->gfd.revents & (G_IO_IN | G_IO_OUT | G_IO_ERR)) ret++;
637 }
638
639 return ret;
640 }
641
642 // like we are about to enter main_loop_select in _ecore_main_select
643 static gboolean
_ecore_main_gsource_prepare(GSource * source EINA_UNUSED,gint * next_time)644 _ecore_main_gsource_prepare(GSource *source EINA_UNUSED,
645 gint *next_time)
646 {
647 Eo *obj = ML_OBJ;
648 Efl_Loop_Data *pd = ML_DAT;
649 gboolean ready = FALSE;
650
651 in_main_loop++;
652 pd->in_loop = in_main_loop;
653
654 if ((!ecore_idling) && (!_ecore_glib_idle_enterer_called))
655 {
656 _update_loop_time(pd);
657 _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time);
658
659 efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
660 _ecore_throttle();
661 _throttle_do(pd);
662 _ecore_glib_idle_enterer_called = FALSE;
663
664 if (pd->fd_handlers_with_buffer)
665 _ecore_main_fd_handlers_buf_call(obj, pd);
666 }
667
668 _ecore_signal_received_process(obj, pd);
669
670 // don't check fds if somebody quit
671 if (g_main_loop_is_running(ecore_main_loop))
672 {
673 // only set idling state in dispatch
674 if (ecore_idling && (!_ecore_main_idlers_exist(pd)) &&
675 (!pd->message_queue))
676 {
677 if (_efl_loop_timers_exists(obj, pd))
678 {
679 int r = -1;
680 double t = _efl_loop_timer_next_get(obj, pd);
681
682 if ((pd->timer_fd >= 0) && (t > 0.0))
683 {
684 struct itimerspec ts;
685
686 ts.it_interval.tv_sec = 0;
687 ts.it_interval.tv_nsec = 0;
688 ts.it_value.tv_sec = t;
689 ts.it_value.tv_nsec = fmod(t * NS_PER_SEC, NS_PER_SEC);
690
691 // timerfd cannot sleep for 0 time
692 if (ts.it_value.tv_sec || ts.it_value.tv_nsec)
693 {
694 r = timerfd_settime(pd->timer_fd, 0, &ts, NULL);
695 if (r < 0)
696 {
697 ERR("timer set returned %d (errno=%d)",
698 r, errno);
699 close(pd->timer_fd);
700 pd->timer_fd = -1;
701 }
702 else INF("sleeping for %ld s %06ldus",
703 ts.it_value.tv_sec,
704 ts.it_value.tv_nsec / 1000);
705 }
706 }
707 if (r == -1)
708 {
709 *next_time = ceil(t * 1000.0);
710 if (t == 0.0) ready = TRUE;
711 }
712 }
713 else *next_time = -1;
714 }
715 else
716 {
717 *next_time = 0;
718 if (pd->message_queue) ready = TRUE;
719 }
720
721 if (pd->fd_handlers_with_prep) _ecore_main_prepare_handlers(obj, pd);
722 }
723 else ready = TRUE;
724
725 in_main_loop--;
726 pd->in_loop = in_main_loop;
727 DBG("leave, timeout = %d", *next_time);
728
729 // ready if we're not running (about to quit)
730 return ready;
731 }
732
733 static gboolean
_ecore_main_gsource_check(GSource * source EINA_UNUSED)734 _ecore_main_gsource_check(GSource *source EINA_UNUSED)
735 {
736 Eo *obj = ML_OBJ;
737 Efl_Loop_Data *pd = ML_DAT;
738 gboolean ret = FALSE;
739
740 in_main_loop++;
741 pd->in_loop = in_main_loop;
742 // check if old timers expired
743 if (ecore_idling && (!_ecore_main_idlers_exist(pd)) &&
744 (!pd->message_queue))
745 {
746 if (pd->timer_fd >= 0)
747 {
748 uint64_t count = 0;
749 int r = read(pd->timer_fd, &count, sizeof count);
750 if ((r == -1) && (errno == EAGAIN))
751 {
752 }
753 else if (r == sizeof count) ret = TRUE;
754 else
755 {
756 // unexpected things happened... fail back to old way
757 ERR("timer read returned %d (errno=%d)", r, errno);
758 close(pd->timer_fd);
759 pd->timer_fd = -1;
760 }
761 }
762 }
763 else ret = TRUE;
764
765 // check if fds are ready
766 #ifdef HAVE_SYS_EPOLL_H
767 if (pd->epoll_fd >= 0)
768 ecore_fds_ready = (_ecore_main_fdh_epoll_mark_active(obj, pd) > 0);
769 else
770 #endif
771 ecore_fds_ready = (_ecore_main_fdh_glib_mark_active(obj, pd) > 0);
772 _ecore_main_fd_handlers_cleanup(obj, pd);
773 if (ecore_fds_ready) ret = TRUE;
774
775 // check timers after updating loop time
776 if (!ret && _efl_loop_timers_exists(obj, pd))
777 ret = (0.0 == _efl_loop_timer_next_get(obj, pd));
778
779 in_main_loop--;
780 pd->in_loop = in_main_loop;
781 return ret;
782 }
783
784 // like we just came out of main_loop_select in _ecore_main_select
785 static gboolean
_ecore_main_gsource_dispatch(GSource * source EINA_UNUSED,GSourceFunc callback EINA_UNUSED,gpointer user_data EINA_UNUSED)786 _ecore_main_gsource_dispatch(GSource *source EINA_UNUSED,
787 GSourceFunc callback EINA_UNUSED,
788 gpointer user_data EINA_UNUSED)
789 {
790 Eo *obj = ML_OBJ;
791 Efl_Loop_Data *pd = ML_DAT;
792 gboolean events_ready, timers_ready, idlers_ready;
793 double next_time;
794
795 _update_loop_time(pd);
796 _efl_loop_timer_enable_new(obj, pd);
797 next_time = _efl_loop_timer_next_get(obj, pd);
798
799 events_ready = pd->message_queue ? 1 : 0;
800 timers_ready = _efl_loop_timers_exists(obj, pd) && (0.0 == next_time);
801 idlers_ready = _ecore_main_idlers_exist(pd);
802
803 in_main_loop++;
804 pd->in_loop = in_main_loop;
805 DBG("enter idling=%d fds=%d events=%d timers=%d (next=%.2f) idlers=%d",
806 ecore_idling, ecore_fds_ready, events_ready,
807 timers_ready, next_time, idlers_ready);
808
809 if (ecore_idling && events_ready)
810 {
811 _ecore_animator_run_reset();
812 eina_file_statgen_next();
813 _ecore_main_pre_idle_exit();
814 efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
815 ecore_idling = 0;
816 }
817 else if (!ecore_idling && !events_ready) ecore_idling = 1;
818
819 if (ecore_idling)
820 {
821 _ecore_main_idler_all_call(obj, pd);
822
823 events_ready = pd->message_queue ? 1 : 0;
824
825 if (ecore_fds_ready || events_ready || timers_ready)
826 {
827 _ecore_animator_run_reset();
828 eina_file_statgen_next();
829 _ecore_main_pre_idle_exit();
830 efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
831 ecore_idling = 0;
832 }
833 }
834
835 // process events
836 if (!ecore_idling)
837 {
838 _ecore_main_fd_handlers_call(obj, pd);
839 if (pd->fd_handlers_with_buffer)
840 _ecore_main_fd_handlers_buf_call(obj, pd);
841 _ecore_signal_received_process(obj, pd);
842 efl_loop_message_process(obj);
843 _ecore_main_fd_handlers_cleanup(obj, pd);
844
845 _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time);
846
847 efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
848 _ecore_throttle();
849 _throttle_do(pd);
850 _ecore_glib_idle_enterer_called = TRUE;
851
852 if (pd->fd_handlers_with_buffer)
853 _ecore_main_fd_handlers_buf_call(obj, pd);
854 }
855
856 in_main_loop--;
857 pd->in_loop = in_main_loop;
858
859 return TRUE; // what should be returned here?
860 }
861
862 static void
_ecore_main_gsource_finalize(GSource * source EINA_UNUSED)863 _ecore_main_gsource_finalize(GSource *source EINA_UNUSED)
864 {
865 }
866
867 static GSourceFuncs ecore_gsource_funcs =
868 {
869 .prepare = _ecore_main_gsource_prepare,
870 .check = _ecore_main_gsource_check,
871 .dispatch = _ecore_main_gsource_dispatch,
872 .finalize = _ecore_main_gsource_finalize,
873 };
874 #endif
875
876 #ifdef HAVE_LIBUV
877 static inline void _ecore_main_loop_uv_check(uv_check_t *handle);
878 static void _ecore_main_loop_uv_prepare(uv_prepare_t *handle);
879
880 static void
_ecore_main_loop_timer_run(uv_timer_t * timer EINA_UNUSED)881 _ecore_main_loop_timer_run(uv_timer_t *timer EINA_UNUSED)
882 {
883 Eo *obj = ML_OBJ;
884 Efl_Loop_Data *pd = ML_DAT;
885
886 if (_ecore_main_uv_idling)
887 {
888 _ecore_main_uv_idling = EINA_FALSE;
889 eina_file_statgen_next();
890 _ecore_main_pre_idle_exit();
891 efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
892 _ecore_animator_run_reset();
893 }
894 _update_loop_time(pd);
895 _ecore_main_loop_uv_check(NULL);
896 _ecore_main_loop_uv_prepare(NULL);
897 }
898
899 static inline void
_ecore_main_loop_uv_check(uv_check_t * handle EINA_UNUSED)900 _ecore_main_loop_uv_check(uv_check_t *handle EINA_UNUSED)
901 {
902 Eo *obj = ML_OBJ;
903 Efl_Loop_Data *pd = ML_DAT;
904
905 DBG("_ecore_main_loop_uv_check idling? %d", (int)_ecore_main_uv_idling);
906 in_main_loop++;
907 pd->in_loop = in_main_loop;
908
909 if (pd->do_quit) goto quit;
910
911 do
912 {
913 _ecore_main_fd_handlers_call(obj, pd);
914 if (pd->fd_handlers_with_buffer)
915 _ecore_main_fd_handlers_buf_call(obj, pd);
916 _ecore_signal_received_process(obj, pd);
917 efl_loop_message_process(obj);
918 _ecore_main_fd_handlers_cleanup(obj, pd);
919 _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time);
920 }
921 while (pd->fd_handlers_to_call);
922 quit:
923 in_main_loop--;
924 pd->in_loop = in_main_loop;
925 }
926 #endif
927
928 static void
_ecore_main_loop_setup(Eo * obj,Efl_Loop_Data * pd)929 _ecore_main_loop_setup(Eo *obj, Efl_Loop_Data *pd)
930 {
931 // Please note that this function is being also called in case of a bad
932 // fd to reset the main loop.
933 #ifdef HAVE_SYS_EPOLL_H
934 pd->epoll_fd = epoll_create(1);
935 if (pd->epoll_fd < 0) WRN("Failed to create epoll fd!");
936 else
937 {
938 eina_file_close_on_exec(pd->epoll_fd, EINA_TRUE);
939
940 pd->epoll_pid = getpid();
941
942 // add polls on all our file descriptors
943 Ecore_Fd_Handler *fdh;
944 EINA_INLIST_FOREACH(pd->fd_handlers, fdh)
945 {
946 if (fdh->delete_me) continue;
947 _ecore_epoll_add(pd->epoll_fd, fdh->fd,
948 _ecore_poll_events_from_fdh(fdh), fdh);
949 _ecore_main_fdh_poll_add(pd, fdh);
950 }
951 }
952 #endif
953
954 if (obj == ML_OBJ)
955 {
956 #ifdef HAVE_LIBUV
957 // XXX: FIXME: the below uv init should not assert but gracefully
958 // fail with errors
959 DBG("loading lib uv");
960 # ifdef HAVE_NODEJS
961 void *lib = dlopen(NULL, RTLD_LAZY);
962 # else
963 void *lib = dlopen("libuv.so.1", RTLD_GLOBAL | RTLD_LAZY);
964 # endif
965
966 if (lib && dlsym(lib, "uv_run"))
967 {
968 DBG("loaded lib uv");
969 _dl_uv_run = dlsym(lib, "uv_run");
970 assert(!!_dl_uv_run);
971 _dl_uv_stop = dlsym(lib, "uv_stop");
972 assert(!!_dl_uv_stop);
973 _dl_uv_default_loop = dlsym(lib, "uv_default_loop");
974 assert(!!_dl_uv_default_loop);
975 _dl_uv_poll_init_socket = dlsym(lib, "uv_poll_init_socket");
976 assert(!!_dl_uv_poll_init_socket);
977 _dl_uv_poll_init = dlsym(lib, "uv_poll_init");
978 assert(!!_dl_uv_poll_init);
979 _dl_uv_poll_start = dlsym(lib, "uv_poll_start");
980 assert(!!_dl_uv_poll_start);
981 _dl_uv_poll_stop = dlsym(lib, "uv_poll_stop");
982 assert(!!_dl_uv_poll_stop);
983 _dl_uv_timer_init = dlsym(lib, "uv_timer_init");
984 assert(!!_dl_uv_timer_init);
985 _dl_uv_timer_start = dlsym(lib, "uv_timer_start");
986 assert(!!_dl_uv_timer_start);
987 _dl_uv_timer_stop = dlsym(lib, "uv_timer_stop");
988 assert(!!_dl_uv_timer_stop);
989 _dl_uv_prepare_init = dlsym(lib, "uv_prepare_init");
990 assert(!!_dl_uv_prepare_init);
991 _dl_uv_prepare_start = dlsym(lib, "uv_prepare_start");
992 assert(!!_dl_uv_prepare_start);
993 _dl_uv_prepare_stop = dlsym(lib, "uv_prepare_stop");
994 assert(!!_dl_uv_prepare_stop);
995 _dl_uv_check_init = dlsym(lib, "uv_check_init");
996 assert(!!_dl_uv_check_init);
997 _dl_uv_check_start = dlsym(lib, "uv_check_start");
998 assert(!!_dl_uv_check_start);
999 _dl_uv_check_stop = dlsym(lib, "uv_check_stop");
1000 assert(!!_dl_uv_check_stop);
1001 _dl_uv_close = dlsym(lib, "uv_close");
1002 assert(!!_dl_uv_close);
1003 _dl_uv_loop_alive = dlsym(lib, "uv_loop_alive");
1004 assert(!!_dl_uv_loop_alive);
1005
1006 //dlclose(lib);
1007
1008 DBG("_dl_uv_prepare_init");
1009 _dl_uv_prepare_init(_dl_uv_default_loop(), &_ecore_main_uv_prepare);
1010 DBG("_dl_uv_prepare_start");
1011 _dl_uv_prepare_start(&_ecore_main_uv_prepare, &_ecore_main_loop_uv_prepare);
1012 DBG("_dl_uv_prepare_started");
1013
1014 DBG("_dl_uv_check_init");
1015 _dl_uv_check_init(_dl_uv_default_loop(), &_ecore_main_uv_check);
1016 DBG("_dl_uv_check_start");
1017 _dl_uv_check_start(&_ecore_main_uv_check, &_ecore_main_loop_uv_check);
1018 DBG("_dl_uv_check_started");
1019
1020 _dl_uv_timer_init(_dl_uv_default_loop(), &_ecore_main_uv_handle_timers);
1021 }
1022 // else
1023 // DBG("did not load uv");
1024 DBG("loaded dlsyms uv");
1025 #endif
1026
1027 // setup for the g_main_loop only integration
1028 #ifdef USE_G_MAIN_LOOP
1029 ecore_glib_source = g_source_new(&ecore_gsource_funcs,
1030 sizeof(GSource));
1031 if (!ecore_glib_source) CRI("Failed to create glib source for epoll!");
1032 else
1033 {
1034 g_source_set_priority(ecore_glib_source,
1035 G_PRIORITY_HIGH_IDLE + 20);
1036 # ifdef HAVE_SYS_EPOLL_H
1037 if (pd->epoll_fd >= 0)
1038 {
1039 // epoll multiplexes fds into the g_main_loop
1040 ecore_epoll_fd.fd = pd->epoll_fd;
1041 ecore_epoll_fd.events = G_IO_IN;
1042 ecore_epoll_fd.revents = 0;
1043 g_source_add_poll(ecore_glib_source, &ecore_epoll_fd);
1044 }
1045 # endif
1046 // timerfd gives us better than millisecond accuracy
1047 pd->timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
1048 if (pd->timer_fd < 0) WRN("failed to create timer fd!");
1049 else
1050 {
1051 eina_file_close_on_exec(pd->timer_fd, EINA_TRUE);
1052 ecore_timer_fd.fd = pd->timer_fd;
1053 ecore_timer_fd.events = G_IO_IN;
1054 ecore_timer_fd.revents = 0;
1055 g_source_add_poll(ecore_glib_source, &ecore_timer_fd);
1056 }
1057
1058 ecore_glib_source_id = g_source_attach(ecore_glib_source, NULL);
1059 if (ecore_glib_source_id <= 0)
1060 CRI("Failed to attach glib source to default context");
1061 }
1062 #endif
1063 }
1064 _ecore_main_timechanges_start(obj);
1065 }
1066
1067 static void
_ecore_main_loop_clear(Eo * obj,Efl_Loop_Data * pd)1068 _ecore_main_loop_clear(Eo *obj, Efl_Loop_Data *pd)
1069 {
1070 if (!pd) return;
1071 // Please note that _ecore_main_loop_shutdown is called in cycle to
1072 // restart the main loop in case of a bad fd
1073 if (obj == ML_OBJ)
1074 {
1075 _ecore_main_timechanges_stop(obj);
1076 #ifdef USE_G_MAIN_LOOP
1077 if (ecore_glib_source)
1078 {
1079 g_source_destroy(ecore_glib_source);
1080 ecore_glib_source = NULL;
1081 }
1082 #endif
1083 #ifdef HAVE_LIBUV
1084 if (_dl_uv_run)
1085 {
1086 DBG("_ecore_main_loop_shutdown");
1087 _dl_uv_timer_stop(&_ecore_main_uv_handle_timers);
1088 _dl_uv_close((uv_handle_t*)&_ecore_main_uv_handle_timers, 0);
1089 }
1090 #endif
1091 }
1092 # ifdef HAVE_SYS_EPOLL_H
1093 if (pd->epoll_fd >= 0)
1094 {
1095 close(pd->epoll_fd);
1096 pd->epoll_fd = -1;
1097 }
1098 #endif
1099 if (pd->timer_fd >= 0)
1100 {
1101 close(pd->timer_fd);
1102 pd->timer_fd = -1;
1103 }
1104 }
1105
1106 void
_ecore_main_loop_init(void)1107 _ecore_main_loop_init(void)
1108 {
1109 DBG("_ecore_main_loop_init");
1110 if (!efl_main_loop_get()) ERR("Cannot create main loop object");
1111 _ecore_main_loop_setup(ML_OBJ, ML_DAT);
1112 }
1113
1114 void
_ecore_main_loop_shutdown(void)1115 _ecore_main_loop_shutdown(void)
1116 {
1117 if (!ML_OBJ) return;
1118 _ecore_main_loop_clear(ML_OBJ, ML_DAT);
1119 // XXX: this seemingly closes fd's it shouldn't.... :( fd 0?
1120 efl_replace(&ML_OBJ, NULL);
1121 ML_DAT = NULL;
1122 }
1123
1124 void
_ecore_main_loop_iterate(Eo * obj,Efl_Loop_Data * pd)1125 _ecore_main_loop_iterate(Eo *obj, Efl_Loop_Data *pd)
1126 {
1127 if (obj == ML_OBJ)
1128 {
1129 #ifdef HAVE_LIBUV
1130 if (!_dl_uv_run)
1131 {
1132 #endif
1133 #ifndef USE_G_MAIN_LOOP
1134 _update_loop_time(pd);
1135 _ecore_main_loop_iterate_internal(obj, pd, 1);
1136 #else
1137 g_main_context_iteration(NULL, 0);
1138 #endif
1139 #ifdef HAVE_LIBUV
1140 }
1141 else
1142 _dl_uv_run(_dl_uv_default_loop(), UV_RUN_ONCE | UV_RUN_NOWAIT);
1143 #endif
1144 }
1145 else
1146 {
1147 #ifndef USE_G_MAIN_LOOP
1148 _update_loop_time(pd);
1149 _ecore_main_loop_iterate_internal(obj, pd, 1);
1150 #else
1151 g_main_context_iteration(NULL, 0);
1152 #endif
1153 }
1154 }
1155
1156 int
_ecore_main_loop_iterate_may_block(Eo * obj,Efl_Loop_Data * pd,int may_block)1157 _ecore_main_loop_iterate_may_block(Eo *obj, Efl_Loop_Data *pd, int may_block)
1158 {
1159 if (obj == ML_OBJ)
1160 {
1161 #ifdef HAVE_LIBUV
1162 if (!_dl_uv_run)
1163 {
1164 #endif
1165 #ifndef USE_G_MAIN_LOOP
1166 in_main_loop++;
1167 pd->in_loop = in_main_loop;
1168 _update_loop_time(pd);
1169 _ecore_main_loop_iterate_internal(obj, pd, !may_block);
1170 in_main_loop--;
1171 pd->in_loop = in_main_loop;
1172 return pd->message_queue ? 1 : 0;
1173 #else
1174 return g_main_context_iteration(NULL, may_block);
1175 #endif
1176 #ifdef HAVE_LIBUV
1177 }
1178 else
1179 _dl_uv_run(_dl_uv_default_loop(),
1180 may_block ? (UV_RUN_ONCE | UV_RUN_NOWAIT) : UV_RUN_ONCE);
1181 #endif
1182 }
1183 else
1184 {
1185 #ifndef USE_G_MAIN_LOOP
1186 pd->in_loop++;
1187 _update_loop_time(pd);
1188 _ecore_main_loop_iterate_internal(obj, pd, !may_block);
1189 pd->in_loop--;
1190 return pd->message_queue ? 1 : 0;
1191 #else
1192 return g_main_context_iteration(NULL, may_block);
1193 #endif
1194 }
1195 return 0;
1196 }
1197
1198 void
_ecore_main_loop_begin(Eo * obj,Efl_Loop_Data * pd)1199 _ecore_main_loop_begin(Eo *obj, Efl_Loop_Data *pd)
1200 {
1201 pd->loop_active++;
1202 if (obj == ML_OBJ)
1203 {
1204 #ifdef HAVE_SYSTEMD
1205 if (getenv("NOTIFY_SOCKET"))
1206 {
1207 _ecore_sd_init();
1208 if (_ecore_sd_notify) _ecore_sd_notify(0, "READY=1");
1209 }
1210 #endif
1211 #ifdef HAVE_LIBUV
1212 if (!_dl_uv_run)
1213 {
1214 #endif
1215 #ifndef USE_G_MAIN_LOOP
1216 in_main_loop++;
1217 pd->in_loop = in_main_loop;
1218 _update_loop_time(pd);
1219 while (!pd->do_quit)
1220 _ecore_main_loop_iterate_internal(obj, pd, 0);
1221 pd->do_quit = 0;
1222 in_main_loop--;
1223 pd->in_loop = in_main_loop;
1224 #else
1225 if (!pd->do_quit)
1226 {
1227 if (!ecore_main_loop)
1228 ecore_main_loop = g_main_loop_new(NULL, FALSE);
1229 g_main_loop_run(ecore_main_loop);
1230 }
1231 pd->do_quit = 0;
1232 #endif
1233 #ifdef HAVE_LIBUV
1234 }
1235 else
1236 {
1237 DBG("uv_run");
1238 in_main_loop++;
1239 pd->in_loop = in_main_loop;
1240 _update_loop_time(pd);
1241 while (!pd->do_quit)
1242 _dl_uv_run(_dl_uv_default_loop(), UV_RUN_DEFAULT);
1243 in_main_loop--;
1244 pd->in_loop = in_main_loop;
1245 pd->do_quit = 0;
1246 DBG("quit");
1247 }
1248 #endif
1249 }
1250 else
1251 {
1252 #ifndef USE_G_MAIN_LOOP
1253 pd->in_loop++;
1254 _update_loop_time(pd);
1255 while (!pd->do_quit)
1256 _ecore_main_loop_iterate_internal(obj, pd, 0);
1257 pd->do_quit = 0;
1258 pd->in_loop--;
1259 #else
1260 if (!pd->do_quit)
1261 {
1262 if (!ecore_main_loop)
1263 ecore_main_loop = g_main_loop_new(NULL, 1);
1264 g_main_loop_run(ecore_main_loop);
1265 }
1266 pd->do_quit = 0;
1267 #endif
1268 }
1269 pd->loop_active--;
1270 }
1271
1272 void
_ecore_main_loop_quit(Eo * obj,Efl_Loop_Data * pd)1273 _ecore_main_loop_quit(Eo *obj, Efl_Loop_Data *pd)
1274 {
1275 if (!pd->loop_active) return;
1276 pd->do_quit = 1;
1277 if (obj != ML_OBJ) return;
1278 #ifdef USE_G_MAIN_LOOP
1279 if (ecore_main_loop) g_main_loop_quit(ecore_main_loop);
1280 #elif defined(HAVE_LIBUV)
1281 if (_dl_uv_run) _dl_uv_stop(_dl_uv_default_loop());
1282 #endif
1283 }
1284
1285 EAPI void
ecore_main_loop_iterate(void)1286 ecore_main_loop_iterate(void)
1287 {
1288 EINA_MAIN_LOOP_CHECK_RETURN;
1289 efl_loop_iterate(ML_OBJ);
1290 }
1291
1292 EAPI int
ecore_main_loop_iterate_may_block(int may_block)1293 ecore_main_loop_iterate_may_block(int may_block)
1294 {
1295 EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
1296 return efl_loop_iterate_may_block(ML_OBJ, may_block);
1297 }
1298
1299 EAPI void
ecore_main_loop_begin(void)1300 ecore_main_loop_begin(void)
1301 {
1302 DBG("ecore_main_loop_begin");
1303 EINA_MAIN_LOOP_CHECK_RETURN;
1304 eina_evlog("+mainloop", NULL, 0.0, NULL);
1305 efl_loop_begin(ML_OBJ);
1306 eina_evlog("-mainloop", NULL, 0.0, NULL);
1307 }
1308
1309 EAPI void
ecore_main_loop_quit(void)1310 ecore_main_loop_quit(void)
1311 {
1312 Eina_Value v = EINA_VALUE_EMPTY;
1313
1314 eina_value_setup(&v, EINA_VALUE_TYPE_INT);
1315 eina_value_set(&v, 0);
1316 EINA_MAIN_LOOP_CHECK_RETURN;
1317 efl_loop_quit(ML_OBJ, v);
1318 }
1319
1320 EAPI int
ecore_main_loop_nested_get(void)1321 ecore_main_loop_nested_get(void)
1322 {
1323 return in_main_loop;
1324 }
1325
1326 EAPI Eina_Bool
ecore_main_loop_animator_ticked_get(void)1327 ecore_main_loop_animator_ticked_get(void)
1328 {
1329 DBG("ecore_main_loop_animator_ticked_get");
1330 return _ecore_animator_run_get();
1331 }
1332
1333 EAPI void
ecore_main_loop_select_func_set(Ecore_Select_Function func)1334 ecore_main_loop_select_func_set(Ecore_Select_Function func)
1335 {
1336 EINA_MAIN_LOOP_CHECK_RETURN;
1337 main_loop_select = func;
1338 }
1339
1340 EAPI Ecore_Select_Function
ecore_main_loop_select_func_get(void)1341 ecore_main_loop_select_func_get(void)
1342 {
1343 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1344 return main_loop_select;
1345 }
1346
1347 Ecore_Fd_Handler *
_ecore_main_fd_handler_add(Eo * obj,Efl_Loop_Data * pd,Eo * handler,int fd,Ecore_Fd_Handler_Flags flags,Ecore_Fd_Cb func,const void * data,Ecore_Fd_Cb buf_func,const void * buf_data,Eina_Bool is_file)1348 _ecore_main_fd_handler_add(Eo *obj,
1349 Efl_Loop_Data *pd,
1350 Eo *handler,
1351 int fd,
1352 Ecore_Fd_Handler_Flags flags,
1353 Ecore_Fd_Cb func,
1354 const void *data,
1355 Ecore_Fd_Cb buf_func,
1356 const void *buf_data,
1357 Eina_Bool is_file)
1358 {
1359 DBG("_ecore_main_fd_handler_add");
1360 Ecore_Fd_Handler *fdh = NULL;
1361
1362 if ((fd < 0) || (flags == 0) || (!func)) return NULL;
1363
1364 fdh = ecore_fd_handler_calloc(1);
1365 if (!fdh) return NULL;
1366 ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER);
1367 fdh->loop = obj;
1368 fdh->loop_data = pd;
1369 fdh->handler = handler;
1370 fdh->fd = fd;
1371 fdh->flags = flags;
1372 fdh->file = is_file;
1373 if (_ecore_main_fdh_poll_add(pd, fdh) < 0)
1374 {
1375 int err = errno;
1376 ERR("Failed to add poll on fd %d (errno = %d: %s)!",
1377 fd, err, strerror(err));
1378 ecore_fd_handler_mp_free(fdh);
1379 return NULL;
1380 }
1381 fdh->func = func;
1382 fdh->data = (void *)data;
1383 fdh->buf_func = buf_func;
1384 if (buf_func)
1385 pd->fd_handlers_with_buffer = eina_list_append
1386 (pd->fd_handlers_with_buffer, fdh);
1387 fdh->buf_data = (void *)buf_data;
1388 if (is_file)
1389 pd->file_fd_handlers = eina_list_append
1390 (pd->file_fd_handlers, fdh);
1391 if (fdh->flags & ECORE_FD_ALWAYS)
1392 pd->always_fd_handlers = eina_list_append
1393 (pd->always_fd_handlers, fdh);
1394 pd->fd_handlers = (Ecore_Fd_Handler *)
1395 eina_inlist_append(EINA_INLIST_GET(pd->fd_handlers),
1396 EINA_INLIST_GET(fdh));
1397 return fdh;
1398 }
1399
1400 void *
_ecore_main_fd_handler_del(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd,Ecore_Fd_Handler * fd_handler)1401 _ecore_main_fd_handler_del(Eo *obj EINA_UNUSED,
1402 Efl_Loop_Data *pd,
1403 Ecore_Fd_Handler *fd_handler)
1404 {
1405 void *r = fd_handler->data;
1406
1407 DBG("_ecore_main_fd_handler_del %p", fd_handler);
1408 if (fd_handler->delete_me)
1409 {
1410 ERR("fdh %p deleted twice", fd_handler);
1411 return NULL;
1412 }
1413
1414 fd_handler->handler = NULL;
1415 fd_handler->delete_me = EINA_TRUE;
1416 if (pd)
1417 {
1418 _ecore_main_fdh_poll_del(pd, fd_handler);
1419 pd->fd_handlers_to_delete = eina_list_append
1420 (pd->fd_handlers_to_delete, fd_handler);
1421 if (fd_handler->prep_func && pd->fd_handlers_with_prep)
1422 pd->fd_handlers_with_prep = eina_list_remove
1423 (pd->fd_handlers_with_prep, fd_handler);
1424 if (fd_handler->buf_func && pd->fd_handlers_with_buffer)
1425 pd->fd_handlers_with_buffer = eina_list_remove
1426 (pd->fd_handlers_with_buffer, fd_handler);
1427 }
1428 else
1429 {
1430 // The main loop is dead by now, so cleanup is required.
1431 ECORE_MAGIC_SET(fd_handler, ECORE_MAGIC_NONE);
1432 ecore_fd_handler_mp_free(fd_handler);
1433 }
1434 return r;
1435 }
1436
1437 EAPI Ecore_Fd_Handler *
ecore_main_fd_handler_add(int fd,Ecore_Fd_Handler_Flags flags,Ecore_Fd_Cb func,const void * data,Ecore_Fd_Cb buf_func,const void * buf_data)1438 ecore_main_fd_handler_add(int fd,
1439 Ecore_Fd_Handler_Flags flags,
1440 Ecore_Fd_Cb func,
1441 const void *data,
1442 Ecore_Fd_Cb buf_func,
1443 const void *buf_data)
1444 {
1445 Ecore_Fd_Handler *fdh = NULL;
1446 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1447 fdh = _ecore_main_fd_handler_add(efl_main_loop_get(),
1448 ML_DAT, NULL, fd, flags, func, data,
1449 buf_func, buf_data, EINA_FALSE);
1450 if (fdh) fdh->legacy = EINA_TRUE;
1451 return fdh;
1452 }
1453
1454 EAPI Ecore_Fd_Handler *
ecore_main_fd_handler_file_add(int fd,Ecore_Fd_Handler_Flags flags,Ecore_Fd_Cb func,const void * data,Ecore_Fd_Cb buf_func,const void * buf_data)1455 ecore_main_fd_handler_file_add(int fd,
1456 Ecore_Fd_Handler_Flags flags,
1457 Ecore_Fd_Cb func,
1458 const void *data,
1459 Ecore_Fd_Cb buf_func,
1460 const void *buf_data)
1461 {
1462 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1463 return _ecore_main_fd_handler_add(efl_main_loop_get(),
1464 ML_DAT, NULL, fd, flags, func, data,
1465 buf_func, buf_data, EINA_TRUE);
1466 }
1467
1468 EAPI void *
ecore_main_fd_handler_del(Ecore_Fd_Handler * fd_handler)1469 ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler)
1470 {
1471 if (!fd_handler) return NULL;
1472 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1473
1474 if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
1475 {
1476 ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
1477 "ecore_main_fd_handler_del");
1478 return NULL;
1479 }
1480 return _ecore_main_fd_handler_del(ML_OBJ, ML_DAT, fd_handler);
1481 }
1482
1483 #ifdef _WIN32
1484 EAPI Ecore_Win32_Handler *
_ecore_main_win32_handler_add(Eo * obj,Efl_Loop_Data * pd,Eo * handler,void * h,Ecore_Win32_Handle_Cb func,const void * data)1485 _ecore_main_win32_handler_add(Eo *obj,
1486 Efl_Loop_Data *pd,
1487 Eo *handler,
1488 void *h,
1489 Ecore_Win32_Handle_Cb func,
1490 const void *data)
1491 {
1492 Ecore_Win32_Handler *wh;
1493
1494 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1495 if (!h || !func) return NULL;
1496
1497 wh = ecore_win32_handler_calloc(1);
1498 if (!wh) return NULL;
1499 ECORE_MAGIC_SET(wh, ECORE_MAGIC_WIN32_HANDLER);
1500 wh->loop = obj;
1501 wh->loop_data = pd;
1502 wh->handler = handler;
1503 wh->h = (HANDLE)h;
1504 wh->func = func;
1505 wh->data = (void *)data;
1506 pd->win32_handlers = (Ecore_Win32_Handler *)
1507 eina_inlist_append(EINA_INLIST_GET(pd->win32_handlers),
1508 EINA_INLIST_GET(wh));
1509 return wh;
1510 }
1511
1512 void *
_ecore_main_win32_handler_del(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd,Ecore_Win32_Handler * win32_handler)1513 _ecore_main_win32_handler_del(Eo *obj EINA_UNUSED,
1514 Efl_Loop_Data *pd,
1515 Ecore_Win32_Handler *win32_handler)
1516 {
1517 if (win32_handler->delete_me)
1518 {
1519 ERR("win32 handler %p deleted twice", win32_handler);
1520 return NULL;
1521 }
1522
1523 win32_handler->delete_me = EINA_TRUE;
1524 win32_handler->handler = NULL;
1525 pd->win32_handlers_to_delete = eina_list_append
1526 (pd->win32_handlers_to_delete, win32_handler);
1527 return win32_handler->data;
1528 }
1529
1530 EAPI Ecore_Win32_Handler *
ecore_main_win32_handler_add(void * h,Ecore_Win32_Handle_Cb func,const void * data)1531 ecore_main_win32_handler_add(void *h,
1532 Ecore_Win32_Handle_Cb func,
1533 const void *data)
1534 {
1535 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1536 return _ecore_main_win32_handler_add(ML_OBJ, ML_DAT, NULL, h, func, data);
1537 }
1538
1539 EAPI void *
ecore_main_win32_handler_del(Ecore_Win32_Handler * win32_handler)1540 ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler)
1541 {
1542 void *ret = NULL;
1543
1544 if (!win32_handler) return NULL;
1545 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1546 if (!ECORE_MAGIC_CHECK(win32_handler, ECORE_MAGIC_WIN32_HANDLER))
1547 {
1548 ECORE_MAGIC_FAIL(win32_handler, ECORE_MAGIC_WIN32_HANDLER,
1549 "ecore_main_win32_handler_del");
1550 return NULL;
1551 }
1552 ret = _ecore_main_win32_handler_del(ML_OBJ, ML_DAT, win32_handler);
1553 return ret;
1554 }
1555 #else
1556 EAPI Ecore_Win32_Handler *
_ecore_main_win32_handler_add(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd EINA_UNUSED,Eo * handler EINA_UNUSED,void * h EINA_UNUSED,Ecore_Win32_Handle_Cb func EINA_UNUSED,const void * data EINA_UNUSED)1557 _ecore_main_win32_handler_add(Eo *obj EINA_UNUSED,
1558 Efl_Loop_Data *pd EINA_UNUSED,
1559 Eo *handler EINA_UNUSED,
1560 void *h EINA_UNUSED,
1561 Ecore_Win32_Handle_Cb func EINA_UNUSED,
1562 const void *data EINA_UNUSED)
1563 {
1564 return NULL;
1565 }
1566
1567 void *
_ecore_main_win32_handler_del(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd EINA_UNUSED,Ecore_Win32_Handler * win32_handler EINA_UNUSED)1568 _ecore_main_win32_handler_del(Eo *obj EINA_UNUSED,
1569 Efl_Loop_Data *pd EINA_UNUSED,
1570 Ecore_Win32_Handler *win32_handler EINA_UNUSED)
1571 {
1572 return NULL;
1573 }
1574
1575 EAPI Ecore_Win32_Handler *
ecore_main_win32_handler_add(void * h EINA_UNUSED,Ecore_Win32_Handle_Cb func EINA_UNUSED,const void * data EINA_UNUSED)1576 ecore_main_win32_handler_add(void *h EINA_UNUSED,
1577 Ecore_Win32_Handle_Cb func EINA_UNUSED,
1578 const void *data EINA_UNUSED)
1579 {
1580 return NULL;
1581 }
1582
1583 EAPI void *
ecore_main_win32_handler_del(Ecore_Win32_Handler * win32_handler EINA_UNUSED)1584 ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler EINA_UNUSED)
1585 {
1586 return NULL;
1587 }
1588 #endif
1589
1590 EAPI void
ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler * fd_handler,Ecore_Fd_Prep_Cb func,const void * data)1591 ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler,
1592 Ecore_Fd_Prep_Cb func,
1593 const void *data)
1594 {
1595 if (!fd_handler) return;
1596 Efl_Loop_Data *pd = fd_handler->loop_data;
1597 EINA_MAIN_LOOP_CHECK_RETURN;
1598
1599 if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
1600 {
1601 ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
1602 "ecore_main_fd_handler_prepare_callback_set");
1603 return;
1604 }
1605 fd_handler->prep_func = func;
1606 fd_handler->prep_data = (void *)data;
1607 if ((!pd->fd_handlers_with_prep) ||
1608 (pd->fd_handlers_with_prep &&
1609 (!eina_list_data_find(pd->fd_handlers_with_prep, fd_handler))))
1610 // FIXME: THIS WILL NOT SCALE WITH LOTS OF PREP FUNCTIONS!!!
1611 pd->fd_handlers_with_prep = eina_list_append
1612 (pd->fd_handlers_with_prep, fd_handler);
1613 }
1614
1615 EAPI int
ecore_main_fd_handler_fd_get(Ecore_Fd_Handler * fd_handler)1616 ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler)
1617 {
1618 if (!fd_handler) return -1;
1619
1620 EINA_MAIN_LOOP_CHECK_RETURN_VAL(-1);
1621
1622 if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
1623 {
1624 ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
1625 "ecore_main_fd_handler_fd_get");
1626 return -1;
1627 }
1628 return fd_handler->fd;
1629 }
1630
1631 EAPI Eina_Bool
ecore_main_fd_handler_active_get(Ecore_Fd_Handler * fd_handler,Ecore_Fd_Handler_Flags flags)1632 ecore_main_fd_handler_active_get(Ecore_Fd_Handler *fd_handler,
1633 Ecore_Fd_Handler_Flags flags)
1634 {
1635 int ret = EINA_FALSE;
1636
1637 EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE);
1638
1639 if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
1640 {
1641 ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
1642 "ecore_main_fd_handler_active_get");
1643 return EINA_FALSE;
1644 }
1645 if ((flags & ECORE_FD_READ) && (fd_handler->read_active)) ret = EINA_TRUE;
1646 if ((flags & ECORE_FD_WRITE) && (fd_handler->write_active)) ret = EINA_TRUE;
1647 if ((flags & ECORE_FD_ERROR) && (fd_handler->error_active)) ret = EINA_TRUE;
1648 return ret;
1649 }
1650
1651 EAPI void
ecore_main_fd_handler_active_set(Ecore_Fd_Handler * fd_handler,Ecore_Fd_Handler_Flags flags)1652 ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler,
1653 Ecore_Fd_Handler_Flags flags)
1654 {
1655 int ret = -1;
1656
1657 if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
1658 {
1659 ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
1660 "ecore_main_fd_handler_active_set");
1661 return;
1662 }
1663 fd_handler->flags = flags;
1664 if (fd_handler->loop_data)
1665 ret = _ecore_main_fdh_poll_modify(fd_handler->loop_data, fd_handler);
1666 if (ret < 0)
1667 ERR("Failed to mod epoll fd %d, loop data=%p: %s!",
1668 fd_handler->fd, fd_handler->loop_data, strerror(errno));
1669 }
1670
1671 void
_ecore_main_content_clear(Eo * obj,Efl_Loop_Data * pd)1672 _ecore_main_content_clear(Eo *obj, Efl_Loop_Data *pd)
1673 {
1674 __eina_promise_cancel_data(obj);
1675
1676 while (pd->fd_handlers)
1677 {
1678 Ecore_Fd_Handler *fdh = pd->fd_handlers;
1679
1680 pd->fd_handlers = (Ecore_Fd_Handler *)
1681 eina_inlist_remove(EINA_INLIST_GET(pd->fd_handlers),
1682 EINA_INLIST_GET(fdh));
1683 if ((fdh->handler) && (fdh->legacy)) efl_del(fdh->handler);
1684 else
1685 {
1686 // XXX: can't do this because this fd handler is legacy and might
1687 // be cleaned up later in object destructors
1688 // ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
1689 // ecore_fd_handler_mp_free(fdh);
1690 }
1691 }
1692 if (pd->fd_handlers_with_buffer)
1693 pd->fd_handlers_with_buffer =
1694 eina_list_free(pd->fd_handlers_with_buffer);
1695 if (pd->fd_handlers_with_prep)
1696 pd->fd_handlers_with_prep =
1697 eina_list_free(pd->fd_handlers_with_prep);
1698 if (pd->file_fd_handlers)
1699 pd->file_fd_handlers =
1700 eina_list_free(pd->file_fd_handlers);
1701 if (pd->always_fd_handlers)
1702 pd->always_fd_handlers =
1703 eina_list_free(pd->always_fd_handlers);
1704 if (pd->fd_handlers_to_delete)
1705 pd->fd_handlers_to_delete =
1706 eina_list_free(pd->fd_handlers_to_delete);
1707 pd->fd_handlers_to_call = NULL;
1708 pd->fd_handlers_to_call_current = NULL;
1709
1710 pd->do_quit = 0;
1711
1712 #ifdef _WIN32
1713 while (pd->win32_handlers)
1714 {
1715 Ecore_Win32_Handler *wh = pd->win32_handlers;
1716
1717 pd->win32_handlers = (Ecore_Win32_Handler *)
1718 eina_inlist_remove(EINA_INLIST_GET(pd->win32_handlers),
1719 EINA_INLIST_GET(wh));
1720 if (wh->handler) efl_del(wh->handler);
1721 else
1722 {
1723 ECORE_MAGIC_SET(wh, ECORE_MAGIC_NONE);
1724 ecore_win32_handler_mp_free(wh);
1725 }
1726 }
1727 if (pd->win32_handlers_to_delete)
1728 pd->win32_handlers_to_delete =
1729 eina_list_free(pd->win32_handlers_to_delete);
1730 pd->win32_handler_current = NULL;
1731 #endif
1732 }
1733
1734 void
_ecore_main_shutdown(void)1735 _ecore_main_shutdown(void)
1736 {
1737 Efl_Loop_Data *pd = ML_DAT;
1738
1739 if (pd->in_loop)
1740 {
1741 ERR("Calling ecore_shutdown() while still in the main loop!!!");
1742 return;
1743 }
1744 }
1745
1746 static void
_ecore_main_prepare_handlers(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd)1747 _ecore_main_prepare_handlers(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
1748 {
1749 Ecore_Fd_Handler *fdh;
1750 Eina_List *l, *l2;
1751
1752 // call the prepare callback for all handlers with prep functions
1753 EINA_LIST_FOREACH_SAFE(pd->fd_handlers_with_prep, l, l2, fdh)
1754 {
1755 if (!fdh)
1756 {
1757 pd->fd_handlers_with_prep = eina_list_remove_list
1758 (l, pd->fd_handlers_with_prep);
1759 continue;
1760 }
1761 if (!fdh->delete_me && fdh->prep_func)
1762 {
1763 fdh->references++;
1764 _ecore_call_prep_cb(fdh->prep_func, fdh->prep_data, fdh);
1765 fdh->references--;
1766 }
1767 else
1768 pd->fd_handlers_with_prep = eina_list_remove_list
1769 (pd->fd_handlers_with_prep, l);
1770 }
1771 }
1772
1773 #if !defined(USE_G_MAIN_LOOP)
1774 static int
_ecore_main_select(Eo * obj,Efl_Loop_Data * pd,double timeout)1775 _ecore_main_select(Eo *obj, Efl_Loop_Data *pd, double timeout)
1776 {
1777 struct timeval tv, *t;
1778 fd_set rfds, wfds, exfds;
1779 Ecore_Fd_Handler *fdh;
1780 Eina_List *l;
1781 int max_fd, ret, outval;
1782 #ifndef _WIN32
1783 int err_no;
1784 #endif
1785
1786 t = NULL;
1787 if ((!ECORE_FINITE(timeout)) || (EINA_DBL_EQ(timeout, 0.0)))
1788 { // finite() tests for NaN, too big, too small, and infinity.
1789 tv.tv_sec = 0;
1790 tv.tv_usec = 0;
1791 t = &tv;
1792 }
1793 else if (timeout > 0.0)
1794 {
1795 int sec, usec;
1796
1797 #ifdef FIX_HZ
1798 timeout += (0.5 / HZ);
1799 sec = (int)timeout;
1800 usec = (int)((timeout - (double)sec) * 1000000);
1801 #else
1802 sec = (int)timeout;
1803 usec = (int)((timeout - (double)sec) * 1000000);
1804 #endif
1805 tv.tv_sec = sec;
1806 tv.tv_usec = usec;
1807 t = &tv;
1808 }
1809 max_fd = 0;
1810 FD_ZERO(&rfds);
1811 FD_ZERO(&wfds);
1812 FD_ZERO(&exfds);
1813
1814 // call the prepare callback for all handlers
1815 if (pd->fd_handlers_with_prep) _ecore_main_prepare_handlers(obj, pd);
1816
1817 #ifdef HAVE_SYS_EPOLL_H
1818 if (pd->epoll_fd < 0)
1819 {
1820 #endif
1821 EINA_INLIST_FOREACH(pd->fd_handlers, fdh)
1822 {
1823 if (!fdh->delete_me)
1824 {
1825 if ((fdh->flags & ECORE_FD_READ) || (fdh->flags & ECORE_FD_ALWAYS))
1826 {
1827 FD_SET(fdh->fd, &rfds);
1828 if (fdh->fd > max_fd) max_fd = fdh->fd;
1829 }
1830 if ((fdh->flags & ECORE_FD_WRITE) || (fdh->flags & ECORE_FD_ALWAYS))
1831 {
1832 FD_SET(fdh->fd, &wfds);
1833 if (fdh->fd > max_fd) max_fd = fdh->fd;
1834 }
1835 if ((fdh->flags & ECORE_FD_ERROR) || (fdh->flags & ECORE_FD_ALWAYS))
1836 {
1837 FD_SET(fdh->fd, &exfds);
1838 if (fdh->fd > max_fd) max_fd = fdh->fd;
1839 }
1840 }
1841 }
1842 #ifdef HAVE_SYS_EPOLL_H
1843 }
1844 else
1845 {
1846 // polling on the epoll fd will wake when fd in the epoll set is active
1847 max_fd = _ecore_get_epoll_fd(obj, pd);
1848 if (max_fd > -1)
1849 FD_SET(max_fd, &rfds);
1850 }
1851 #endif
1852 EINA_LIST_FOREACH(pd->file_fd_handlers, l, fdh)
1853 {
1854 if (!fdh->delete_me)
1855 {
1856 if ((fdh->flags & ECORE_FD_READ) || (fdh->flags & ECORE_FD_ALWAYS))
1857 {
1858 FD_SET(fdh->fd, &rfds);
1859 if (fdh->fd > max_fd) max_fd = fdh->fd;
1860 }
1861 if ((fdh->flags & ECORE_FD_WRITE) || (fdh->flags & ECORE_FD_ALWAYS))
1862 {
1863 FD_SET(fdh->fd, &wfds);
1864 if (fdh->fd > max_fd) max_fd = fdh->fd;
1865 }
1866 if ((fdh->flags & ECORE_FD_ERROR) || (fdh->flags & ECORE_FD_ALWAYS))
1867 {
1868 FD_SET(fdh->fd, &exfds);
1869 if (fdh->fd > max_fd) max_fd = fdh->fd;
1870 }
1871 if (fdh->fd > max_fd) max_fd = fdh->fd;
1872 }
1873 }
1874 if (_ecore_signal_count_get(obj, pd)) return -1;
1875
1876 eina_evlog("<RUN", NULL, 0.0, NULL);
1877 eina_evlog("!SLEEP", NULL, 0.0, t ? "timeout" : "forever");
1878 if (obj == ML_OBJ)
1879 ret = main_loop_select(max_fd + 1, &rfds, &wfds, &exfds, t);
1880 else
1881 ret = general_loop_select(max_fd + 1, &rfds, &wfds, &exfds, t);
1882 #ifndef _WIN32
1883 err_no = errno;
1884 #endif
1885 eina_evlog("!WAKE", NULL, 0.0, NULL);
1886 eina_evlog(">RUN", NULL, 0.0, NULL);
1887
1888 _update_loop_time(pd);
1889 if (ret < 0)
1890 {
1891 #ifndef _WIN32
1892 if (err_no == EINTR)
1893 {
1894 outval = -1;
1895 goto BAIL;
1896 }
1897 else if (err_no == EBADF) _ecore_main_fd_handlers_bads_rem(obj, pd);
1898 #endif
1899 }
1900 if (ret > 0)
1901 {
1902 #ifdef HAVE_SYS_EPOLL_H
1903 if (pd->epoll_fd >= 0)
1904 _ecore_main_fdh_epoll_mark_active(obj, pd);
1905 else
1906 #endif
1907 {
1908 EINA_INLIST_FOREACH(pd->fd_handlers, fdh)
1909 {
1910 if (!fdh->delete_me)
1911 {
1912 if (FD_ISSET(fdh->fd, &rfds))
1913 fdh->read_active = EINA_TRUE;
1914 if (FD_ISSET(fdh->fd, &wfds))
1915 fdh->write_active = EINA_TRUE;
1916 if (FD_ISSET(fdh->fd, &exfds))
1917 fdh->error_active = EINA_TRUE;
1918 _ecore_try_add_to_call_list(obj, pd, fdh);
1919 }
1920 }
1921 }
1922 EINA_LIST_FOREACH(pd->file_fd_handlers, l, fdh)
1923 {
1924 if (!fdh->delete_me)
1925 {
1926 if (FD_ISSET(fdh->fd, &rfds))
1927 fdh->read_active = EINA_TRUE;
1928 if (FD_ISSET(fdh->fd, &wfds))
1929 fdh->write_active = EINA_TRUE;
1930 if (FD_ISSET(fdh->fd, &exfds))
1931 fdh->error_active = EINA_TRUE;
1932 _ecore_try_add_to_call_list(obj, pd, fdh);
1933 }
1934 }
1935 outval = 1;
1936 goto BAIL;
1937 }
1938 outval = 0;
1939 BAIL:
1940 EINA_LIST_FOREACH(pd->always_fd_handlers, l, fdh)
1941 _ecore_try_add_to_call_list(obj, pd, fdh);
1942
1943 if (ret > 0)
1944 {
1945 _ecore_main_fd_handlers_cleanup(obj, pd);
1946 #ifdef _WIN32
1947 _ecore_main_win32_handlers_cleanup(obj, pd);
1948 #endif
1949 }
1950 return outval || pd->always_fd_handlers;
1951 }
1952
1953 #endif
1954
1955 #ifndef _WIN32
1956 # ifndef USE_G_MAIN_LOOP
1957 static void
_ecore_main_fd_handlers_bads_rem(Eo * obj,Efl_Loop_Data * pd)1958 _ecore_main_fd_handlers_bads_rem(Eo *obj, Efl_Loop_Data *pd)
1959 {
1960 Ecore_Fd_Handler *fdh;
1961 Eina_Inlist *l;
1962 int found = 0;
1963
1964 ERR("Removing bad fds");
1965 for (l = EINA_INLIST_GET(pd->fd_handlers); l; )
1966 {
1967 fdh = (Ecore_Fd_Handler *)l;
1968 l = l->next;
1969 errno = 0;
1970
1971 if ((fcntl(fdh->fd, F_GETFD) < 0) && (errno == EBADF))
1972 {
1973 ERR("Found bad fd at index %d", fdh->fd);
1974 if (fdh->flags & ECORE_FD_ERROR)
1975 {
1976 ERR("Fd set for error! calling user");
1977 fdh->references++;
1978 if (!_ecore_call_fd_cb(fdh->func, fdh->data, fdh))
1979 {
1980 ERR("Fd function err returned 0, remove it");
1981 if (!fdh->delete_me)
1982 {
1983 fdh->delete_me = EINA_TRUE;
1984 _ecore_main_fdh_poll_del(pd, fdh);
1985 pd->fd_handlers_to_delete =
1986 eina_list_append(pd->fd_handlers_to_delete, fdh);
1987 }
1988 found++;
1989 }
1990 fdh->references--;
1991 }
1992 else
1993 {
1994 ERR("Problematic fd found at %d! setting it for delete",
1995 fdh->fd);
1996 if (!fdh->delete_me)
1997 {
1998 fdh->delete_me = EINA_TRUE;
1999 _ecore_main_fdh_poll_del(pd, fdh);
2000 pd->fd_handlers_to_delete =
2001 eina_list_append(pd->fd_handlers_to_delete, fdh);
2002 }
2003
2004 found++;
2005 }
2006 }
2007 }
2008 if (found == 0)
2009 {
2010 # ifdef HAVE_GLIB
2011 ERR("No bad fd found. Maybe a foreign fd from glib?");
2012 # else
2013 ERR("No bad fd found. EEEK!");
2014 # endif
2015 }
2016 _ecore_main_fd_handlers_cleanup(obj, pd);
2017 }
2018
2019 # endif
2020 #endif
2021
2022 static void
_ecore_main_fd_handlers_cleanup(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd)2023 _ecore_main_fd_handlers_cleanup(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
2024 {
2025 Ecore_Fd_Handler *fdh, *last;
2026 Eina_List *l, *l2;
2027
2028 // Cleanup deleted caller from the list
2029 last = NULL;
2030 fdh = pd->fd_handlers_to_call;
2031 while (fdh)
2032 {
2033 if (fdh->delete_me)
2034 {
2035 if (!last)
2036 pd->fd_handlers_to_call = fdh == fdh->next_ready ?
2037 NULL : fdh->next_ready;
2038 else
2039 last->next_ready = fdh == fdh->next_ready ?
2040 last : fdh->next_ready;
2041 }
2042 else last = fdh;
2043
2044 if (fdh == fdh->next_ready) break;
2045 fdh = fdh->next_ready;
2046 }
2047
2048 if (!pd->fd_handlers_to_delete) return;
2049 EINA_LIST_FOREACH_SAFE(pd->fd_handlers_to_delete, l, l2, fdh)
2050 {
2051 if (!fdh)
2052 {
2053 pd->fd_handlers_to_delete = eina_list_remove_list
2054 (l, pd->fd_handlers_to_delete);
2055 continue;
2056 }
2057 if (fdh->references) continue;
2058 if (pd->fd_handlers_to_call_current == fdh)
2059 pd->fd_handlers_to_call_current = NULL;
2060 if (fdh->buf_func && pd->fd_handlers_with_buffer)
2061 pd->fd_handlers_with_buffer = eina_list_remove
2062 (pd->fd_handlers_with_buffer, fdh);
2063 if (fdh->prep_func && pd->fd_handlers_with_prep)
2064 pd->fd_handlers_with_prep = eina_list_remove
2065 (pd->fd_handlers_with_prep, fdh);
2066 pd->fd_handlers = (Ecore_Fd_Handler *)
2067 eina_inlist_remove(EINA_INLIST_GET(pd->fd_handlers),
2068 EINA_INLIST_GET(fdh));
2069 if (fdh->file)
2070 pd->file_fd_handlers = eina_list_remove(pd->file_fd_handlers, fdh);
2071 if (fdh->flags & ECORE_FD_ALWAYS)
2072 pd->always_fd_handlers = eina_list_remove(pd->always_fd_handlers, fdh);
2073 ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
2074 ecore_fd_handler_mp_free(fdh);
2075 pd->fd_handlers_to_delete = eina_list_remove_list
2076 (pd->fd_handlers_to_delete, l);
2077 }
2078 }
2079
2080 #ifdef _WIN32
2081 static void
_ecore_main_win32_handlers_cleanup(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd)2082 _ecore_main_win32_handlers_cleanup(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
2083 {
2084 Ecore_Win32_Handler *wh;
2085 Eina_List *l, *l2;
2086
2087 if (!pd->win32_handlers_to_delete) return;
2088 EINA_LIST_FOREACH_SAFE(pd->win32_handlers_to_delete, l, l2, wh)
2089 {
2090 if (!wh)
2091 {
2092 pd->win32_handlers_to_delete = eina_list_remove_list
2093 (l, pd->win32_handlers_to_delete);
2094 continue;
2095 }
2096 // wh->delete_me should be set for all whs at the start of the list
2097 if (wh->references) continue;
2098 pd->win32_handlers = (Ecore_Win32_Handler *)
2099 eina_inlist_remove(EINA_INLIST_GET(pd->win32_handlers),
2100 EINA_INLIST_GET(wh));
2101 ECORE_MAGIC_SET(wh, ECORE_MAGIC_NONE);
2102 ecore_win32_handler_mp_free(wh);
2103 pd->win32_handlers_to_delete = eina_list_remove_list
2104 (pd->win32_handlers_to_delete, l);
2105 }
2106 }
2107 #endif
2108
2109 static void
_ecore_main_fd_handlers_call(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd)2110 _ecore_main_fd_handlers_call(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
2111 {
2112 // grab a new list
2113 if (!pd->fd_handlers_to_call_current)
2114 {
2115 pd->fd_handlers_to_call_current = pd->fd_handlers_to_call;
2116 pd->fd_handlers_to_call = NULL;
2117 }
2118
2119 if (!pd->fd_handlers_to_call_current) return;
2120 eina_evlog("+fd_handlers", NULL, 0.0, NULL);
2121
2122 while (pd->fd_handlers_to_call_current)
2123 {
2124 Ecore_Fd_Handler *fdh = pd->fd_handlers_to_call_current;
2125
2126 if (!fdh->delete_me)
2127 {
2128 if ((fdh->read_active) ||
2129 (fdh->write_active) ||
2130 (fdh->error_active) ||
2131 (fdh->flags & ECORE_FD_ALWAYS))
2132 {
2133 fdh->references++;
2134 if (!_ecore_call_fd_cb(fdh->func, fdh->data, fdh))
2135 {
2136 if (!fdh->delete_me)
2137 {
2138 fdh->delete_me = EINA_TRUE;
2139 _ecore_main_fdh_poll_del(pd, fdh);
2140 pd->fd_handlers_to_delete = eina_list_append
2141 (pd->fd_handlers_to_delete, fdh);
2142 }
2143 }
2144 fdh->references--;
2145 #ifdef EFL_EXTRA_SANITY_CHECKS
2146 _ecore_fd_valid(obj, pd);
2147 #endif
2148 fdh->read_active = EINA_FALSE;
2149 fdh->write_active = EINA_FALSE;
2150 fdh->error_active = EINA_FALSE;
2151 }
2152 }
2153
2154 // stop when we point to ourselves
2155 if (fdh->next_ready == fdh)
2156 {
2157 fdh->next_ready = NULL;
2158 pd->fd_handlers_to_call_current = NULL;
2159 break;
2160 }
2161
2162 pd->fd_handlers_to_call_current = fdh->next_ready;
2163 fdh->next_ready = NULL;
2164 }
2165 eina_evlog("-fd_handlers", NULL, 0.0, NULL);
2166 }
2167
2168 static int
_ecore_main_fd_handlers_buf_call(Eo * obj,Efl_Loop_Data * pd)2169 _ecore_main_fd_handlers_buf_call(Eo *obj, Efl_Loop_Data *pd)
2170 {
2171 Ecore_Fd_Handler *fdh;
2172 Eina_List *l, *l2;
2173 int ret;
2174
2175 if (!pd->fd_handlers_with_buffer) return 0;
2176 eina_evlog("+fd_handlers_buf", NULL, 0.0, NULL);
2177 ret = 0;
2178 EINA_LIST_FOREACH_SAFE(pd->fd_handlers_with_buffer, l, l2, fdh)
2179 {
2180 if (!fdh)
2181 {
2182 pd->fd_handlers_with_buffer = eina_list_remove_list
2183 (l, pd->fd_handlers_with_buffer);
2184 continue;
2185 }
2186 if ((!fdh->delete_me) && fdh->buf_func)
2187 {
2188 fdh->references++;
2189 if (_ecore_call_fd_cb(fdh->buf_func, fdh->buf_data, fdh))
2190 {
2191 ret |= _ecore_call_fd_cb(fdh->func, fdh->data, fdh);
2192 fdh->read_active = EINA_TRUE;
2193 _ecore_try_add_to_call_list(obj, pd, fdh);
2194 }
2195 fdh->references--;
2196 }
2197 else
2198 pd->fd_handlers_with_buffer = eina_list_remove_list
2199 (pd->fd_handlers_with_buffer, l);
2200 }
2201 eina_evlog("-fd_handlers_buf", NULL, 0.0, NULL);
2202 return ret;
2203 }
2204
2205 #ifdef HAVE_LIBUV
2206 static void
_ecore_main_loop_uv_prepare(uv_prepare_t * handle EINA_UNUSED)2207 _ecore_main_loop_uv_prepare(uv_prepare_t *handle EINA_UNUSED)
2208 {
2209 Eo *obj = ML_OBJ;
2210 Efl_Loop_Data *pd = ML_DAT;
2211 double t = -1;
2212
2213 _dl_uv_timer_stop(&_ecore_main_uv_handle_timers);
2214 if ((pd->in_loop == 0) && (pd->do_quit))
2215 {
2216 _ecore_main_fd_handlers_cleanup(obj, pd);
2217
2218 while (pd->fd_handlers)
2219 {
2220 Ecore_Fd_Handler *fdh = pd->fd_handlers;
2221 pd->fd_handlers = (Ecore_Fd_Handler *)
2222 eina_inlist_remove(EINA_INLIST_GET(pd->fd_handlers),
2223 EINA_INLIST_GET(fdh));
2224 fdh->delete_me = 1;
2225 _ecore_main_fdh_poll_del(pd, fdh);
2226 ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
2227 ecore_fd_handler_mp_free(fdh);
2228 }
2229 if (pd->fd_handlers_with_buffer)
2230 pd->fd_handlers_with_buffer = eina_list_free(pd->fd_handlers_with_buffer);
2231 if (pd->fd_handlers_with_prep)
2232 pd->fd_handlers_with_prep = eina_list_free(pd->fd_handlers_with_prep);
2233 if (pd->fd_handlers_to_delete)
2234 pd->fd_handlers_to_delete = eina_list_free(pd->fd_handlers_to_delete);
2235 if (pd->file_fd_handlers)
2236 pd->file_fd_handlers = eina_list_free(pd->file_fd_handlers);
2237
2238 pd->fd_handlers_to_call = NULL;
2239 pd->fd_handlers_to_call_current = NULL;
2240
2241 _dl_uv_prepare_stop(&_ecore_main_uv_prepare);
2242 _dl_uv_check_stop(&_ecore_main_uv_check);
2243 _dl_uv_stop(_dl_uv_default_loop());
2244
2245 return;
2246 }
2247
2248 in_main_loop++;
2249 pd->in_loop = in_main_loop;
2250
2251 if (!_ecore_main_uv_idling)
2252 {
2253 _ecore_main_uv_idling = EINA_TRUE;
2254 efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
2255 _ecore_throttle();
2256 _throttle_do(pd);
2257 }
2258
2259 if (_ecore_main_uv_idling)
2260 {
2261 _ecore_main_idler_all_call(obj, pd);
2262 DBG("called idles");
2263 if (_ecore_main_idlers_exist(pd) || (pd->message_queue)) t = 0.0;
2264 }
2265
2266 if (pd->do_quit)
2267 {
2268 DBG("do quit outside loop");
2269
2270 if (_ecore_main_uv_idling)
2271 {
2272 eina_file_statgen_next();
2273 _ecore_main_pre_idle_exit();
2274 efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
2275 _ecore_animator_run_reset();
2276 _ecore_main_uv_idling = EINA_FALSE;
2277 }
2278 t = -1;
2279 _update_loop_time(pd);
2280 _efl_loop_timer_enable_new(obj, pd);
2281 goto done;
2282 }
2283
2284 assert(!pd->fd_handlers_to_call);
2285
2286 _update_loop_time(pd);
2287 _efl_loop_timer_enable_new(obj, pd);
2288 if (_efl_loop_timers_exists(obj, pd) || (t >= 0))
2289 {
2290 double tnext = _efl_loop_timer_next_get(obj, pd);
2291
2292 if ((t < 0) || ((tnext >= 0) && (tnext < t))) t = tnext;
2293 DBG("Should awake after %f", t);
2294
2295 if (t >= 0.0)
2296 {
2297 // _dl_uv_timer_stop(&_ecore_main_uv_handle_timers);
2298 _dl_uv_timer_start(&_ecore_main_uv_handle_timers,
2299 &_ecore_main_loop_timer_run,
2300 t * 1000, 0);
2301 }
2302 else DBG("Is not going to awake with timer");
2303 }
2304 else DBG("Is not going to awake with timer");
2305
2306 done:
2307 if (pd->fd_handlers_with_prep) _ecore_main_prepare_handlers(obj, pd);
2308 in_main_loop--;
2309 pd->in_loop = in_main_loop;
2310 }
2311 #endif
2312
2313 #if !defined(USE_G_MAIN_LOOP)
2314 enum {
2315 SPIN_MORE,
2316 SPIN_RESTART,
2317 LOOP_CONTINUE
2318 };
2319
2320 static int
_ecore_main_loop_spin_core(Eo * obj,Efl_Loop_Data * pd)2321 _ecore_main_loop_spin_core(Eo *obj, Efl_Loop_Data *pd)
2322 {
2323 // as we are spinning we need to update loop time per spin
2324 _update_loop_time(pd);
2325 // call all idlers
2326 _ecore_main_idler_all_call(obj, pd);
2327 // which returns false if no more idelrs exist
2328 if (!_ecore_main_idlers_exist(pd)) return SPIN_RESTART;
2329 // sneaky - drop through or if checks - the first one to succeed
2330 // drops through and returns "continue" so further ones dont run
2331 if ((_ecore_main_select(obj, pd, 0.0) > 0) || (pd->message_queue) ||
2332 (_ecore_signal_count_get(obj, pd) > 0) || (pd->do_quit))
2333 return LOOP_CONTINUE;
2334 // default - spin more
2335 return SPIN_MORE;
2336 }
2337
2338 static int
_ecore_main_loop_spin_no_timers(Eo * obj,Efl_Loop_Data * pd)2339 _ecore_main_loop_spin_no_timers(Eo *obj, Efl_Loop_Data *pd)
2340 {
2341 // if we have idlers we HAVE to spin and handle everything
2342 // in a polling way - spin in a tight polling loop
2343 for (;;)
2344 {
2345 int action = _ecore_main_loop_spin_core(obj, pd);
2346 if (action != SPIN_MORE) return action;
2347 // if an idler has added a timer then we need to go through
2348 // the start of the spin cycle again to handle cases properly
2349 if (_efl_loop_timers_exists(obj, pd)) return SPIN_RESTART;
2350 }
2351 // just contiune handling events etc.
2352 return LOOP_CONTINUE;
2353 }
2354
2355 static int
_ecore_main_loop_spin_timers(Eo * obj,Efl_Loop_Data * pd)2356 _ecore_main_loop_spin_timers(Eo *obj, Efl_Loop_Data *pd)
2357 {
2358 // if we have idlers we HAVE to spin and handle everything
2359 // in a polling way - spin in a tight polling loop
2360 for (;;)
2361 {
2362 int action = _ecore_main_loop_spin_core(obj, pd);
2363 if (action != SPIN_MORE) return action;
2364 // if next timer expires now or in the past - stop spinning and
2365 // continue the mainloop walk as our "select" timeout has
2366 // expired now
2367 if (_efl_loop_timer_next_get(obj, pd) <= 0.0) return LOOP_CONTINUE;
2368 }
2369 // just contiune handling events etc.
2370 return LOOP_CONTINUE;
2371 }
2372
2373 static void
_ecore_fps_marker_1(void)2374 _ecore_fps_marker_1(void)
2375 {
2376 if (!_ecore_fps_debug) return;
2377 t2 = ecore_time_get();
2378 if ((t1 > 0.0) && (t2 > 0.0)) _ecore_fps_debug_runtime_add(t2 - t1);
2379 }
2380
2381 static void
_ecore_fps_marker_2(void)2382 _ecore_fps_marker_2(void)
2383 {
2384 if (!_ecore_fps_debug) return;
2385 t1 = ecore_time_get();
2386 }
2387
2388 static void
_ecore_main_loop_iterate_internal(Eo * obj,Efl_Loop_Data * pd,int once_only)2389 _ecore_main_loop_iterate_internal(Eo *obj, Efl_Loop_Data *pd, int once_only)
2390 {
2391 double next_time = -1.0;
2392
2393 if (obj == ML_OBJ)
2394 {
2395 in_main_loop++;
2396 pd->in_loop = in_main_loop;
2397 }
2398 // expire any timers
2399 _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time);
2400 // process signals into events ....
2401 if (obj == ML_OBJ) _ecore_signal_received_process(obj, pd);
2402 // if as a result of timers/animators or signals we have accumulated
2403 // events, then instantly handle them
2404 if (pd->message_queue)
2405 {
2406 // but first conceptually enter an idle state
2407 efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
2408 _ecore_throttle();
2409 _throttle_do(pd);
2410 // now quickly poll to see which input fd's are active
2411 _ecore_main_select(obj, pd, 0.0);
2412 // allow newly queued timers to expire from now on
2413 _efl_loop_timer_enable_new(obj, pd);
2414 // go straight to processing the events we had queued
2415 goto process_all;
2416 }
2417
2418 if (once_only)
2419 {
2420 // in once_only mode we should quickly poll for inputs, signals
2421 // if we got any events or signals, allow new timers to process.
2422 // use bitwise or to force both conditions to be tested and
2423 // merged together
2424 if (_ecore_main_select(obj, pd, 0.0) |
2425 _ecore_signal_count_get(obj, pd))
2426 {
2427 _efl_loop_timer_enable_new(obj, pd);
2428 goto process_all;
2429 }
2430 }
2431 else
2432 {
2433 // call idle enterers ...
2434 efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
2435 _ecore_throttle();
2436 _throttle_do(pd);
2437 }
2438
2439 // if these calls caused any buffered events to appear - deal with them
2440 if (pd->fd_handlers_with_buffer)
2441 _ecore_main_fd_handlers_buf_call(obj, pd);
2442
2443 // if there are any (buffered fd handling may generate them)
2444 // then jump to processing them */
2445 if (pd->message_queue)
2446 {
2447 _ecore_main_select(obj, pd, 0.0);
2448 _efl_loop_timer_enable_new(obj, pd);
2449 goto process_all;
2450 }
2451
2452 if (once_only)
2453 {
2454 // in once_only mode enter idle here instead and then return
2455 efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
2456 _ecore_throttle();
2457 _throttle_do(pd);
2458 _efl_loop_timer_enable_new(obj, pd);
2459 goto done;
2460 }
2461
2462 if (obj == ML_OBJ) _ecore_fps_marker_1();
2463
2464 // start of the sleeping or looping section
2465 start_loop: //-*************************************************************
2466 // any timers re-added as a result of these are allowed to go
2467 _efl_loop_timer_enable_new(obj, pd);
2468 // if we have been asked to quit the mainloop then exit at this point
2469 if (pd->do_quit)
2470 {
2471 _efl_loop_timer_enable_new(obj, pd);
2472 goto done;
2473 }
2474 if (!pd->message_queue)
2475 {
2476 // init flags
2477 next_time = _efl_loop_timer_next_get(obj, pd);
2478 // no idlers
2479 if (!_ecore_main_idlers_exist(pd))
2480 {
2481 // sleep until timeout or forever (-1.0) waiting for on fds
2482 _ecore_main_select(obj, pd, next_time);
2483 }
2484 else
2485 {
2486 int action = LOOP_CONTINUE;
2487
2488 // no timers - spin
2489 if (next_time < 0) action = _ecore_main_loop_spin_no_timers(obj, pd);
2490 // timers - spin
2491 else action = _ecore_main_loop_spin_timers(obj, pd);
2492 if (action == SPIN_RESTART) goto start_loop;
2493 }
2494 }
2495 if (obj == ML_OBJ) _ecore_fps_marker_2();
2496
2497 // actually wake up and deal with input, events etc.
2498 process_all: //-*********************************************************
2499
2500 // we came out of our "wait state" so idle has exited
2501 if (!once_only)
2502 {
2503 _ecore_animator_run_reset(); // XXX:
2504 eina_file_statgen_next();
2505 _ecore_main_pre_idle_exit();
2506 efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
2507 }
2508 // call the fd handler per fd that became alive...
2509 // this should read or write any data to the monitored fd and then
2510 // post events onto the ecore event pipe if necessary
2511 _ecore_main_fd_handlers_call(obj, pd);
2512 if (pd->fd_handlers_with_buffer) _ecore_main_fd_handlers_buf_call(obj, pd);
2513 // process signals into events ....
2514 _ecore_signal_received_process(obj, pd);
2515 // handle events ...
2516 efl_loop_message_process(obj);
2517 _ecore_main_fd_handlers_cleanup(obj, pd);
2518
2519 if (once_only)
2520 {
2521 // if in once_only mode handle idle exiting
2522 efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
2523 _ecore_throttle();
2524 _throttle_do(pd);
2525 }
2526
2527 done: //-*****************************************************************
2528 // Agressively flush animator
2529 _ecore_animator_flush();
2530 if (!once_only)
2531 eina_slstr_local_clear(); // Free all short lived strings
2532
2533 if (obj == ML_OBJ)
2534 {
2535 in_main_loop--;
2536 pd->in_loop = in_main_loop;
2537 }
2538 }
2539
2540 #endif
2541
2542 #ifdef _WIN32
2543 typedef struct
2544 {
2545 DWORD objects_nbr;
2546 HANDLE *objects;
2547 DWORD timeout;
2548 } Ecore_Main_Win32_Thread_Data;
2549
2550 static unsigned int __stdcall
_ecore_main_win32_objects_wait_thread(void * data)2551 _ecore_main_win32_objects_wait_thread(void *data)
2552 {
2553 Ecore_Main_Win32_Thread_Data *td = (Ecore_Main_Win32_Thread_Data *)data;
2554 return MsgWaitForMultipleObjects(td->objects_nbr,
2555 (const HANDLE *)td->objects,
2556 FALSE,
2557 td->timeout,
2558 QS_ALLINPUT);
2559 }
2560
2561 static DWORD
_ecore_main_win32_objects_wait(DWORD objects_nbr,const HANDLE * objects,DWORD timeout)2562 _ecore_main_win32_objects_wait(DWORD objects_nbr,
2563 const HANDLE *objects,
2564 DWORD timeout)
2565 {
2566 Ecore_Main_Win32_Thread_Data *threads_data;
2567 HANDLE *threads_handles;
2568 DWORD threads_nbr, threads_remain, objects_idx, result, i;
2569
2570 if (objects_nbr < MAXIMUM_WAIT_OBJECTS)
2571 return MsgWaitForMultipleObjects(objects_nbr,
2572 objects,
2573 EINA_FALSE,
2574 timeout, QS_ALLINPUT);
2575 // too much objects, so we launch a bunch of threads to
2576 // wait for, each one calls MsgWaitForMultipleObjects
2577
2578 threads_nbr = objects_nbr / (MAXIMUM_WAIT_OBJECTS - 1);
2579 threads_remain = objects_nbr % (MAXIMUM_WAIT_OBJECTS - 1);
2580 if (threads_remain > 0) threads_nbr++;
2581
2582 if (threads_nbr > MAXIMUM_WAIT_OBJECTS)
2583 {
2584 CRI("Too much objects to wait for (%lu).", objects_nbr);
2585 return WAIT_FAILED;
2586 }
2587
2588 threads_handles = (HANDLE *)malloc(threads_nbr * sizeof(HANDLE));
2589 if (!threads_handles)
2590 {
2591 ERR("Can not allocate memory for the waiting thread.");
2592 return WAIT_FAILED;
2593 }
2594
2595 threads_data = (Ecore_Main_Win32_Thread_Data *)
2596 malloc(threads_nbr * sizeof(Ecore_Main_Win32_Thread_Data));
2597 if (!threads_data)
2598 {
2599 ERR("Can not allocate memory for the waiting thread.");
2600 goto free_threads_handles;
2601 }
2602
2603 objects_idx = 0;
2604 for (i = 0; i < threads_nbr; i++)
2605 {
2606 threads_data[i].timeout = timeout;
2607 threads_data[i].objects = (HANDLE *)objects + objects_idx;
2608
2609 if ((i == (threads_nbr - 1)) && (threads_remain != 0))
2610 {
2611 threads_data[i].objects_nbr = threads_remain;
2612 objects_idx += threads_remain;
2613 }
2614 else
2615 {
2616 threads_data[i].objects_nbr = (MAXIMUM_WAIT_OBJECTS - 1);
2617 objects_idx += (MAXIMUM_WAIT_OBJECTS - 1);
2618 }
2619
2620 threads_handles[i] = (HANDLE)_beginthreadex
2621 (NULL, 0, _ecore_main_win32_objects_wait_thread,
2622 &threads_data[i], 0, NULL);
2623 if (!threads_handles[i])
2624 {
2625 DWORD j;
2626
2627 ERR("Can not create the waiting threads.");
2628 WaitForMultipleObjects(i, threads_handles, TRUE, INFINITE);
2629 for (j = 0; j < i; j++)
2630 CloseHandle(threads_handles[i]);
2631
2632 goto free_threads_data;
2633 }
2634 }
2635
2636 result = WaitForMultipleObjects(threads_nbr,
2637 threads_handles,
2638 FALSE, // we wait until one thread signaled
2639 INFINITE);
2640
2641 if (result < (WAIT_OBJECT_0 + threads_nbr))
2642 {
2643 DWORD wait_res;
2644
2645 // One of the thread callback has exited so we retrieve
2646 // its exit status, that is the returned value of
2647 // MsgWaitForMultipleObjects()
2648 if (GetExitCodeThread(threads_handles[result - WAIT_OBJECT_0],
2649 &wait_res))
2650 {
2651 WaitForMultipleObjects(threads_nbr, threads_handles,
2652 TRUE, INFINITE);
2653 for (i = 0; i < threads_nbr; i++)
2654 CloseHandle(threads_handles[i]);
2655 free(threads_data);
2656 free(threads_handles);
2657 return wait_res;
2658 }
2659 }
2660 else
2661 {
2662 ERR("Error when waiting threads.");
2663 if (result == WAIT_FAILED)
2664 ERR("%s", evil_last_error_get());
2665 goto close_thread;
2666 }
2667
2668 close_thread:
2669 WaitForMultipleObjects(threads_nbr, threads_handles, TRUE, INFINITE);
2670 for (i = 0; i < threads_nbr; i++) CloseHandle(threads_handles[i]);
2671 free_threads_data:
2672 free(threads_data);
2673 free_threads_handles:
2674 free(threads_handles);
2675
2676 return WAIT_FAILED;
2677 }
2678
2679 static unsigned int
_stdin_wait_thread(void * data EINA_UNUSED)2680 _stdin_wait_thread(void *data EINA_UNUSED)
2681 {
2682 int c = getc(stdin);
2683 ungetc(c, stdin);
2684 return 0;
2685 }
2686
2687 static int
_ecore_main_win32_select(int nfds EINA_UNUSED,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * tv)2688 _ecore_main_win32_select(int nfds EINA_UNUSED,
2689 fd_set *readfds,
2690 fd_set *writefds,
2691 fd_set *exceptfds,
2692 struct timeval *tv)
2693 {
2694 Efl_Loop_Data *pd = ML_DAT;
2695 HANDLE *objects;
2696 int *sockets;
2697 Ecore_Fd_Handler *fdh;
2698 Ecore_Win32_Handler *wh;
2699 static HANDLE stdin_wait_thread = INVALID_HANDLE_VALUE;
2700 HANDLE stdin_handle;
2701 DWORD result, timeout;
2702 MSG msg;
2703 unsigned int fds_nbr = 0;
2704 unsigned int objects_nbr = 0;
2705 unsigned int events_nbr = 0;
2706 unsigned int i;
2707 int res;
2708 Eina_Bool stdin_thread_done = EINA_FALSE;
2709
2710 fds_nbr = eina_inlist_count(EINA_INLIST_GET(pd->fd_handlers));
2711 sockets = (int *)malloc(fds_nbr * sizeof(int));
2712 if (!sockets) return -1;
2713
2714 objects = (HANDLE)malloc((fds_nbr +
2715 eina_inlist_count
2716 (EINA_INLIST_GET(pd->win32_handlers)))
2717 * sizeof(HANDLE));
2718 if (!objects)
2719 {
2720 free(sockets);
2721 return -1;
2722 }
2723
2724 // Create an event object per socket
2725 EINA_INLIST_FOREACH(pd->fd_handlers, fdh)
2726 {
2727 if (fdh->delete_me) continue;
2728
2729 WSAEVENT event;
2730 long network_event;
2731
2732 network_event = 0;
2733 if (readfds)
2734 {
2735 if (FD_ISSET(fdh->fd, readfds))
2736 network_event |= FD_READ | FD_CONNECT | FD_ACCEPT;
2737 }
2738 if (writefds)
2739 {
2740 if (FD_ISSET(fdh->fd, writefds))
2741 network_event |= FD_WRITE | FD_CLOSE;
2742 }
2743 if (exceptfds)
2744 {
2745 if (FD_ISSET(fdh->fd, exceptfds))
2746 network_event |= FD_OOB;
2747 }
2748
2749 if (network_event)
2750 {
2751 event = WSACreateEvent();
2752 WSAEventSelect(fdh->fd, event, network_event);
2753 objects[objects_nbr] = event;
2754 sockets[events_nbr] = fdh->fd;
2755 events_nbr++;
2756 objects_nbr++;
2757 }
2758 }
2759 stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
2760 // store the HANDLEs in the objects to wait for
2761 EINA_INLIST_FOREACH(pd->win32_handlers, wh)
2762 {
2763 if (wh->delete_me) continue;
2764
2765 if (wh->h == stdin_handle)
2766 {
2767 if (stdin_wait_thread == INVALID_HANDLE_VALUE)
2768 stdin_wait_thread = (HANDLE)_beginthreadex(NULL,
2769 0,
2770 _stdin_wait_thread,
2771 NULL,
2772 0,
2773 NULL);
2774 objects[objects_nbr] = stdin_wait_thread;
2775 }
2776 else objects[objects_nbr] = wh->h;
2777 objects_nbr++;
2778 }
2779
2780 // Empty the queue before waiting
2781 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2782 {
2783 TranslateMessage(&msg);
2784 DispatchMessage(&msg);
2785 }
2786
2787 // Wait for any message sent or posted to this queue
2788 // or for one of the passed handles be set to signaled.
2789 if (!tv) timeout = INFINITE;
2790 else timeout = (DWORD)((tv->tv_sec * 1000.0) + (tv->tv_usec / 1000.0));
2791
2792 if (timeout == 0)
2793 {
2794 res = 0;
2795 goto err;
2796 }
2797
2798 result = _ecore_main_win32_objects_wait(objects_nbr,
2799 (const HANDLE *)objects,
2800 timeout);
2801 if (readfds) FD_ZERO(readfds);
2802 if (writefds) FD_ZERO(writefds);
2803 if (exceptfds) FD_ZERO(exceptfds);
2804 // The result tells us the type of event we have.
2805 if (result == WAIT_FAILED)
2806 {
2807 WRN("%s", evil_last_error_get());
2808 res = -1;
2809 }
2810 else if (result == WAIT_TIMEOUT)
2811 {
2812 INF("time-out interval elapsed.");
2813 res = 0;
2814 }
2815 else if (result == (WAIT_OBJECT_0 + objects_nbr))
2816 {
2817 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2818 {
2819 TranslateMessage(&msg);
2820 DispatchMessage(&msg);
2821 }
2822 res = 0;
2823 }
2824 else if (result < WAIT_OBJECT_0 + events_nbr)
2825 {
2826 WSANETWORKEVENTS network_event;
2827
2828 WSAEnumNetworkEvents(sockets[result], objects[result], &network_event);
2829 if ((network_event.lNetworkEvents &
2830 (FD_READ | FD_CONNECT | FD_ACCEPT)) && readfds)
2831 FD_SET(sockets[result], readfds);
2832 if ((network_event.lNetworkEvents &
2833 (FD_WRITE | FD_CLOSE)) && writefds)
2834 FD_SET(sockets[result], writefds);
2835 if ((network_event.lNetworkEvents & FD_OOB) && exceptfds)
2836 FD_SET(sockets[result], exceptfds);
2837 res = 1;
2838 }
2839 else if ((result >= (WAIT_OBJECT_0 + events_nbr)) &&
2840 (result < (WAIT_OBJECT_0 + objects_nbr)))
2841 {
2842 if (!pd->win32_handler_current)
2843 // regular main loop, start from head
2844 pd->win32_handler_current = pd->win32_handlers;
2845 else
2846 // recursive main loop, continue from where we were
2847 pd->win32_handler_current = (Ecore_Win32_Handler *)
2848 EINA_INLIST_GET(pd->win32_handler_current)->next;
2849
2850 if (objects[result - WAIT_OBJECT_0] == stdin_wait_thread)
2851 stdin_thread_done = EINA_TRUE;
2852
2853 while (pd->win32_handler_current)
2854 {
2855 wh = pd->win32_handler_current;
2856
2857 if ((objects[result - WAIT_OBJECT_0] == wh->h) ||
2858 ((objects[result - WAIT_OBJECT_0] == stdin_wait_thread) &&
2859 (wh->h == stdin_handle)))
2860 {
2861 if (!wh->delete_me)
2862 {
2863 wh->references++;
2864 if (!wh->func(wh->data, wh))
2865 {
2866 wh->delete_me = EINA_TRUE;
2867 pd->win32_handlers_to_delete = eina_list_append
2868 (pd->win32_handlers_to_delete, wh);
2869 }
2870 wh->references--;
2871 }
2872 }
2873 if (pd->win32_handler_current)
2874 // may have changed in recursive main loops
2875 pd->win32_handler_current = (Ecore_Win32_Handler *)
2876 EINA_INLIST_GET(pd->win32_handler_current)->next;
2877 }
2878 res = 1;
2879 }
2880 else
2881 {
2882 ERR("unknown result...\n");
2883 res = -1;
2884 }
2885
2886 err:
2887 // Remove event objects again
2888 for (i = 0; i < events_nbr; i++) WSACloseEvent(objects[i]);
2889
2890 if (stdin_thread_done) stdin_wait_thread = INVALID_HANDLE_VALUE;
2891
2892 free(objects);
2893 free(sockets);
2894 return res;
2895 }
2896 #endif
2897