2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
10 # include <winsock2.h>
15 #include <sys/types.h>
22 # include <sys/param.h>
28 #include "ecore_private.h"
31 static int _ecore_main_select(double timeout);
32 static void _ecore_main_fd_handlers_cleanup(void);
33 static void _ecore_main_fd_handlers_call(void);
34 static int _ecore_main_fd_handlers_buf_call(void);
35 static void _ecore_main_loop_iterate_internal(int once_only);
37 static int in_main_loop = 0;
38 static int do_quit = 0;
39 static Ecore_Fd_Handler *fd_handlers = NULL;
40 static int fd_handlers_delete_me = 0;
42 static double t1 = 0.0;
43 static double t2 = 0.0;
46 * @defgroup Ecore_Main_Loop_Group Main Loop Functions
48 * These functions control the Ecore event handling loop. This loop is
49 * designed to work on embedded systems all the way to large and
50 * powerful mutli-cpu workstations.
52 * It serialises all system signals and events into a single event
53 * queue, that can be easily processed without needing to worry about
54 * concurrency. A properly written, event-driven program using this
55 * kind of programming does not need threads. It makes the program very
56 * robust and easy to follow.
58 * Here is an example of simple program and its basic event loop flow:
59 * @image html prog_flow.png
61 * For examples of setting up and using a main loop, see
62 * @ref event_handler_example.c and @ref timer_example.c.
66 * Runs a single iteration of the main loop to process everything on the
68 * @ingroup Ecore_Main_Loop_Group
71 ecore_main_loop_iterate(void)
73 _ecore_main_loop_iterate_internal(1);
77 * Runs the application main loop.
79 * This function will not return until @ref ecore_main_loop_quit is called.
81 * @ingroup Ecore_Main_Loop_Group
84 ecore_main_loop_begin(void)
87 for (;do_quit == 0;) _ecore_main_loop_iterate_internal(0);
93 * Quits the main loop once all the events currently on the queue have
95 * @ingroup Ecore_Main_Loop_Group
98 ecore_main_loop_quit(void)
104 * @defgroup Ecore_FD_Handler_Group File Event Handling Functions
106 * Functions that deal with file descriptor handlers.
110 * Adds a callback for activity on the given file descriptor.
112 * @p func will be called during the execution of @ref ecore_main_loop_begin
113 * when the file descriptor is available for reading, or writing, or both.
115 * Normally the return value from the @p func is "zero means this handler is
116 * finished and can be deleted" as is usual for handler callbacks. However,
117 * if the @p buf_func is supplied, then the return value from the @p func is
118 * "non zero means the handler should be called again in a tight loop".
120 * @p buf_func is called during event loop handling to check if data that has
121 * been read from the file descriptor is in a buffer and is available to
122 * read. Some systems (notably xlib) handle their own buffering, and would
123 * otherwise not work with select(). These systems should use a @p buf_func.
124 * This is a most annoying hack, only ecore_x uses it, so refer to that for
125 * an example. NOTE - @p func should probably return "one" always if
126 * @p buf_func is used, to avoid confusion with the other return value
129 * @param fd The file descriptor to watch.
130 * @param flags To watch it for read (@c ECORE_FD_READ) and/or
131 * (@c ECORE_FD_WRITE) write ability. @c ECORE_FD_ERROR
133 * @param func The callback function.
134 * @param data The data to pass to the callback.
135 * @param buf_func The function to call to check if any data has been
136 * buffered and already read from the fd. Can be @c NULL.
137 * @param buf_data The data to pass to the @p buf_func function.
138 * @return A fd handler handle if successful. @c NULL otherwise.
139 * @ingroup Ecore_FD_Handler_Group
141 EAPI Ecore_Fd_Handler *
142 ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, int (*func) (void *data, Ecore_Fd_Handler *fd_handler), const void *data, int (*buf_func) (void *buf_data, Ecore_Fd_Handler *fd_handler), const void *buf_data)
144 Ecore_Fd_Handler *fdh;
148 (!func)) return NULL;
149 fdh = calloc(1, sizeof(Ecore_Fd_Handler));
150 if (!fdh) return NULL;
151 ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER);
154 fdh->read_active = 0;
155 fdh->write_active = 0;
156 fdh->error_active = 0;
159 fdh->data = (void *)data;
160 fdh->buf_func = buf_func;
161 fdh->buf_data = (void *)buf_data;
162 fd_handlers = _ecore_list2_append(fd_handlers, fdh);
167 * Deletes the given FD handler.
168 * @param fd_handler The given FD handler.
169 * @return The data pointer set using @ref ecore_main_fd_handler_add,
170 * for @p fd_handler on success. @c NULL otherwise.
171 * @ingroup Ecore_FD_Handler_Group
174 ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler)
176 if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
178 ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
179 "ecore_main_fd_handler_del");
182 fd_handler->delete_me = 1;
183 fd_handlers_delete_me = 1;
184 return fd_handler->data;
188 ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler, void (*func) (void *data, Ecore_Fd_Handler *fd_handler), const void *data)
190 if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
192 ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
193 "ecore_main_fd_handler_prepare_callback_set");
196 fd_handler->prep_func = func;
197 fd_handler->prep_data = (void *) data;
201 * Retrieves the file descriptor that the given handler is handling.
202 * @param fd_handler The given FD handler.
203 * @return The file descriptor the handler is watching.
204 * @ingroup Ecore_FD_Handler_Group
207 ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler)
209 if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
211 ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
212 "ecore_main_fd_handler_fd_get");
215 return fd_handler->fd;
219 * Return if read, write or error, or a combination thereof, is active on the
220 * file descriptor of the given FD handler.
221 * @param fd_handler The given FD handler.
222 * @param flags The flags, @c ECORE_FD_READ, @c ECORE_FD_WRITE or
223 * @c ECORE_FD_ERROR to query.
224 * @return @c 1 if any of the given flags are active. @c 0 otherwise.
225 * @ingroup Ecore_FD_Handler_Group
228 ecore_main_fd_handler_active_get(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags)
232 if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
234 ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
235 "ecore_main_fd_handler_active_get");
239 if ((flags & ECORE_FD_READ) && (fd_handler->read_active)) ret = 1;
240 if ((flags & ECORE_FD_WRITE) && (fd_handler->write_active)) ret = 1;
241 if ((flags & ECORE_FD_ERROR) && (fd_handler->error_active)) ret = 1;
246 * Set what active streams the given FD handler should be monitoring.
247 * @param fd_handler The given FD handler.
248 * @param flags The flags to be watching.
249 * @ingroup Ecore_FD_Handler_Group
252 ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags)
254 if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
256 ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
257 "ecore_main_fd_handler_active_set");
260 fd_handler->flags = flags;
264 _ecore_main_shutdown(void)
270 "*** ECORE WARINING: Calling ecore_shutdown() while still in the main loop.\n"
271 "*** Program may crash or behave strangely now.\n");
276 Ecore_Fd_Handler *fdh;
279 fd_handlers = _ecore_list2_remove(fd_handlers, fdh);
280 ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
283 fd_handlers_delete_me = 0;
287 _ecore_main_select(double timeout)
289 struct timeval tv, *t;
290 fd_set rfds, wfds, exfds;
296 if ((!finite(timeout)) || (timeout == 0.0)) /* finite() tests for NaN, too big, too small, and infinity. */
302 else if (timeout > 0.0)
307 timeout += (0.5 / HZ);
309 usec = (int)((timeout - (double)sec) * 1000000);
312 usec = (int)((timeout - (double)sec) * 1000000);
323 /* call the prepare callback for all handlers */
324 for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
326 Ecore_Fd_Handler *fdh;
328 fdh = (Ecore_Fd_Handler *)l;
330 if (!fdh->delete_me && fdh->prep_func)
331 fdh->prep_func (fdh->prep_data, fdh);
333 for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
335 Ecore_Fd_Handler *fdh;
337 fdh = (Ecore_Fd_Handler *)l;
338 if (fdh->flags & ECORE_FD_READ)
340 FD_SET(fdh->fd, &rfds);
341 if (fdh->fd > max_fd) max_fd = fdh->fd;
343 if (fdh->flags & ECORE_FD_WRITE)
345 FD_SET(fdh->fd, &wfds);
346 if (fdh->fd > max_fd) max_fd = fdh->fd;
348 if (fdh->flags & ECORE_FD_ERROR)
350 FD_SET(fdh->fd, &exfds);
351 if (fdh->fd > max_fd) max_fd = fdh->fd;
354 if (_ecore_signal_count_get()) return -1;
355 ret = select(max_fd + 1, &rfds, &wfds, &exfds, t);
358 if (errno == EINTR) return -1;
362 for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
364 Ecore_Fd_Handler *fdh;
366 fdh = (Ecore_Fd_Handler *)l;
369 if (FD_ISSET(fdh->fd, &rfds))
370 fdh->read_active = 1;
371 if (FD_ISSET(fdh->fd, &wfds))
372 fdh->write_active = 1;
373 if (FD_ISSET(fdh->fd, &exfds))
374 fdh->error_active = 1;
377 _ecore_main_fd_handlers_cleanup();
384 _ecore_main_fd_handlers_cleanup(void)
388 if (!fd_handlers_delete_me) return;
389 for (l = (Ecore_List2 *)fd_handlers; l;)
391 Ecore_Fd_Handler *fdh;
393 fdh = (Ecore_Fd_Handler *)l;
397 fd_handlers = _ecore_list2_remove(fd_handlers, fdh);
398 ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
402 fd_handlers_delete_me = 0;
406 _ecore_main_fd_handlers_call(void)
410 for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
412 Ecore_Fd_Handler *fdh;
414 fdh = (Ecore_Fd_Handler *)l;
417 if ((fdh->read_active) ||
418 (fdh->write_active) ||
421 if (!fdh->func(fdh->data, fdh))
424 fd_handlers_delete_me = 1;
426 fdh->read_active = 0;
427 fdh->write_active = 0;
428 fdh->error_active = 0;
435 _ecore_main_fd_handlers_buf_call(void)
441 for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
443 Ecore_Fd_Handler *fdh;
445 fdh = (Ecore_Fd_Handler *)l;
450 if (fdh->buf_func(fdh->buf_data, fdh))
452 ret |= fdh->func(fdh->data, fdh);
453 fdh->read_active = 1;
462 _ecore_main_win32_message(double timeout)
467 if (!finite(timeout))
474 if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
483 start = ecore_time_get();
484 while ((t = ecore_time_get()) < (start + timeout))
486 if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
496 _ecore_main_win32_message_buf_call(void)
503 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
505 if ((msg.message & 0xffff) < 0xC000)
507 TranslateMessage(&msg);
508 DispatchMessage(&msg);
520 _ecore_main_loop_iterate_internal(int once_only)
528 /* expire any timers */
532 now = ecore_time_get();
533 while (_ecore_timer_call(now));
534 _ecore_timer_cleanup();
536 /* any timers re-added as a result of these are allowed to go */
537 _ecore_timer_enable_new();
538 /* process signals into events .... */
539 while (_ecore_signal_count_get()) _ecore_signal_call();
540 if (_ecore_event_exist())
545 _ecore_main_select(0.0);
546 _ecore_main_win32_message(0.0);
549 /* call idle enterers ... */
551 _ecore_idle_enterer_call();
554 have_event = have_signal = have_msg = 0;
556 if (_ecore_main_select(0.0) > 0) have_event = 1;
558 if (_ecore_main_win32_message(0.0) > 0) have_msg = 1;
559 if (_ecore_signal_count_get() > 0) have_signal = 1;
561 if (have_signal || have_event || have_msg)
565 /* if these calls caused any buffered events to appear - deal with them */
566 while (_ecore_main_fd_handlers_buf_call());
567 while (_ecore_main_win32_message_buf_call());
569 /* if ther are any - jump to processing them */
570 if (_ecore_event_exist())
575 _ecore_main_select(0.0);
576 _ecore_main_win32_message(0.0);
581 _ecore_idle_enterer_call();
586 if (_ecore_fps_debug)
588 t2 = ecore_time_get();
589 if ((t1 > 0.0) && (t2 > 0.0))
590 _ecore_fps_debug_runtime_add(t2 - t1);
598 if (!_ecore_event_exist())
601 have_event = have_signal = have_msg = 0;
602 next_time = _ecore_timer_next_get();
607 if (!_ecore_idler_exist())
609 if (_ecore_main_select(-1.0) > 0) have_event = 1;
610 if (_ecore_main_win32_message(-1.0) > 0) have_msg = 1;
611 if (_ecore_signal_count_get() > 0) have_signal = 1;
618 if (!_ecore_idler_call()) goto start_loop;
619 if (_ecore_event_exist()) break;
620 if (_ecore_main_select(0.0) > 0) have_event = 1;
621 if (_ecore_main_win32_message(0.0) > 0) have_msg = 1;
622 if (_ecore_signal_count_get() > 0) have_signal = 1;
623 if (have_event || have_signal || have_msg) break;
624 next_time = _ecore_timer_next_get();
625 if (next_time >= 0) goto start_loop;
634 if (!_ecore_idler_exist())
636 if (_ecore_main_select(next_time) > 0) have_event = 1;
637 if (_ecore_main_win32_message(next_time) > 0) have_msg = 1;
638 if (_ecore_signal_count_get() > 0) have_signal = 1;
647 if (!_ecore_idler_call()) goto start_loop;
648 if (_ecore_event_exist()) break;
649 if (_ecore_main_select(0.0) > 0) have_event = 1;
650 if (_ecore_main_win32_message(0.0) > 0) have_msg = 1;
651 if (_ecore_signal_count_get() > 0) have_signal = 1;
652 if (have_event || have_signal || have_msg) break;
653 cur_time = ecore_time_get();
654 t = ecore_time_get() - cur_time;
655 if (t >= next_time) break;
656 next_time = _ecore_timer_next_get();
657 if (next_time < 0) goto start_loop;
663 if (_ecore_fps_debug)
665 t1 = ecore_time_get();
667 /* we came out of our "wait state" so idle has exited */
669 _ecore_idle_exiter_call();
670 /* call the fd handler per fd that became alive... */
671 /* this should read or write any data to the monitored fd and then */
672 /* post events onto the ecore event pipe if necessary */
674 if (have_event) _ecore_main_fd_handlers_call();
677 /* process signals into events .... */
678 while (_ecore_signal_count_get()) _ecore_signal_call();
679 /* handle events ... */
681 _ecore_main_fd_handlers_cleanup();
683 while (_ecore_main_fd_handlers_buf_call());
684 if (have_msg) _ecore_main_win32_message_buf_call();
685 while (_ecore_main_win32_message_buf_call());
686 /* ok - too much optimising. let's call idle enterers more often. if we
687 * have events that place more events or jobs etc. on the event queue
688 * we may never get to call an idle enterer
691 _ecore_idle_enterer_call();