4ba6856f5a08e0c2957fb7ac87e15d1a402715e5
[framework/uifw/ecore.git] / src / lib / ecore / ecore_main.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8
9 #ifdef _WIN32
10 # include <winsock2.h>
11 #endif
12
13 #include <math.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <unistd.h>
17 #include <errno.h>
18
19 #define FIX_HZ 1
20
21 #ifdef FIX_HZ
22 # include <sys/param.h>
23 # ifndef HZ
24 #  define HZ 100
25 # endif
26 #endif
27
28 #include "ecore_private.h"
29 #include "Ecore.h"
30
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);
36
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;
41
42 static double            t1 = 0.0;
43 static double            t2 = 0.0;
44
45 /**
46  * @defgroup Ecore_Main_Loop_Group Main Loop Functions
47  *
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.
51  *
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.
57  *
58  * Here is an example of simple program and its basic event loop flow:
59  * @image html prog_flow.png
60  *
61  * For examples of setting up and using a main loop, see
62  * @ref event_handler_example.c and @ref timer_example.c.
63  */
64
65 /**
66  * Runs a single iteration of the main loop to process everything on the
67  * queue.
68  * @ingroup Ecore_Main_Loop_Group
69  */
70 EAPI void
71 ecore_main_loop_iterate(void)
72 {
73    _ecore_main_loop_iterate_internal(1);
74 }
75
76 /**
77  * Runs the application main loop.
78  *
79  * This function will not return until @ref ecore_main_loop_quit is called.
80  *
81  * @ingroup Ecore_Main_Loop_Group
82  */
83 EAPI void
84 ecore_main_loop_begin(void)
85 {
86    in_main_loop++;
87    for (;do_quit == 0;) _ecore_main_loop_iterate_internal(0);
88    do_quit = 0;
89    in_main_loop--;
90 }
91
92 /**
93  * Quits the main loop once all the events currently on the queue have
94  * been processed.
95  * @ingroup Ecore_Main_Loop_Group
96  */
97 EAPI void
98 ecore_main_loop_quit(void)
99 {
100    do_quit = 1;
101 }
102
103 /**
104  * @defgroup Ecore_FD_Handler_Group File Event Handling Functions
105  *
106  * Functions that deal with file descriptor handlers.
107  */
108
109 /**
110  * Adds a callback for activity on the given file descriptor.
111  *
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.
114  *
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".
119  *
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 
127  * semantics.
128  *
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
132  *
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
140  */
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)
143 {
144    Ecore_Fd_Handler *fdh;
145
146    if ((fd < 0) ||
147        (flags == 0) ||
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);
152    fdh->fd = fd;
153    fdh->flags = flags;
154    fdh->read_active = 0;
155    fdh->write_active = 0;
156    fdh->error_active = 0;
157    fdh->delete_me = 0;
158    fdh->func = func;
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);
163    return fdh;
164 }
165
166 /**
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
172  */
173 EAPI void *
174 ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler)
175 {
176    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
177      {
178         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
179                          "ecore_main_fd_handler_del");
180         return NULL;
181      }
182    fd_handler->delete_me = 1;
183    fd_handlers_delete_me = 1;
184    return fd_handler->data;
185 }
186
187 EAPI void
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)
189 {
190    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
191      {
192         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
193                          "ecore_main_fd_handler_prepare_callback_set");
194         return;
195      }
196    fd_handler->prep_func = func;
197    fd_handler->prep_data = (void *) data;
198 }
199
200 /**
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
205  */
206 EAPI int
207 ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler)
208 {
209    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
210      {
211         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
212                          "ecore_main_fd_handler_fd_get");
213         return -1;
214      }
215    return fd_handler->fd;
216 }
217
218 /**
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
226  */
227 EAPI int
228 ecore_main_fd_handler_active_get(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags)
229 {
230    int ret;
231
232    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
233      {
234         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
235                          "ecore_main_fd_handler_active_get");
236         return 0;
237      }
238    ret = 0;
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;
242    return ret;
243 }
244
245 /**
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
250  */
251 EAPI void
252 ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags)
253 {
254    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
255      {
256         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
257                          "ecore_main_fd_handler_active_set");
258         return;
259      }
260    fd_handler->flags = flags;
261 }
262
263 void
264 _ecore_main_shutdown(void)
265 {
266    if (in_main_loop)
267      {
268         fprintf(stderr,
269                 "\n"
270                 "*** ECORE WARINING: Calling ecore_shutdown() while still in the main loop.\n"
271                 "***                 Program may crash or behave strangely now.\n");
272         return;
273      }
274    while (fd_handlers)
275      {
276         Ecore_Fd_Handler *fdh;
277
278         fdh = fd_handlers;
279         fd_handlers = _ecore_list2_remove(fd_handlers, fdh);
280         ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
281         free(fdh);
282      }
283    fd_handlers_delete_me = 0;
284 }
285
286 static int
287 _ecore_main_select(double timeout)
288 {
289    struct timeval tv, *t;
290    fd_set         rfds, wfds, exfds;
291    int            max_fd;
292    int            ret;
293    Ecore_List2    *l;
294
295    t = NULL;
296    if ((!finite(timeout)) || (timeout == 0.0))  /* finite() tests for NaN, too big, too small, and infinity.  */
297      {
298         tv.tv_sec = 0;
299         tv.tv_usec = 0;
300         t = &tv;
301      }
302    else if (timeout > 0.0)
303      {
304         int sec, usec;
305
306 #ifdef FIX_HZ
307         timeout += (0.5 / HZ);
308         sec = (int)timeout;
309         usec = (int)((timeout - (double)sec) * 1000000);
310 #else
311         sec = (int)timeout;
312         usec = (int)((timeout - (double)sec) * 1000000);
313 #endif
314         tv.tv_sec = sec;
315         tv.tv_usec = usec;
316         t = &tv;
317      }
318    max_fd = 0;
319    FD_ZERO(&rfds);
320    FD_ZERO(&wfds);
321    FD_ZERO(&exfds);
322
323    /* call the prepare callback for all handlers */
324    for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
325      {
326         Ecore_Fd_Handler *fdh;
327
328         fdh = (Ecore_Fd_Handler *)l;
329
330         if (!fdh->delete_me && fdh->prep_func)
331                 fdh->prep_func (fdh->prep_data, fdh);
332      }
333    for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
334      {
335         Ecore_Fd_Handler *fdh;
336
337         fdh = (Ecore_Fd_Handler *)l;
338         if (fdh->flags & ECORE_FD_READ)
339           {
340              FD_SET(fdh->fd, &rfds);
341              if (fdh->fd > max_fd) max_fd = fdh->fd;
342           }
343         if (fdh->flags & ECORE_FD_WRITE)
344           {
345              FD_SET(fdh->fd, &wfds);
346              if (fdh->fd > max_fd) max_fd = fdh->fd;
347           }
348         if (fdh->flags & ECORE_FD_ERROR)
349           {
350              FD_SET(fdh->fd, &exfds);
351              if (fdh->fd > max_fd) max_fd = fdh->fd;
352           }
353      }
354    if (_ecore_signal_count_get()) return -1;
355    ret = select(max_fd + 1, &rfds, &wfds, &exfds, t);
356    if (ret < 0)
357      {
358         if (errno == EINTR) return -1;
359      }
360    if (ret > 0)
361      {
362         for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
363           {
364              Ecore_Fd_Handler *fdh;
365
366              fdh = (Ecore_Fd_Handler *)l;
367              if (!fdh->delete_me)
368                {
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;
375                }
376           }
377         _ecore_main_fd_handlers_cleanup();
378         return 1;
379      }
380    return 0;
381 }
382
383 static void
384 _ecore_main_fd_handlers_cleanup(void)
385 {
386    Ecore_List2 *l;
387
388    if (!fd_handlers_delete_me) return;
389    for (l = (Ecore_List2 *)fd_handlers; l;)
390      {
391         Ecore_Fd_Handler *fdh;
392
393         fdh = (Ecore_Fd_Handler *)l;
394         l = l->next;
395         if (fdh->delete_me)
396           {
397              fd_handlers = _ecore_list2_remove(fd_handlers, fdh);
398              ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
399              free(fdh);
400           }
401      }
402    fd_handlers_delete_me = 0;
403 }
404
405 static void
406 _ecore_main_fd_handlers_call(void)
407 {
408    Ecore_List2    *l;
409
410    for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
411      {
412         Ecore_Fd_Handler *fdh;
413
414         fdh = (Ecore_Fd_Handler *)l;
415         if (!fdh->delete_me)
416           {
417              if ((fdh->read_active) ||
418                  (fdh->write_active) ||
419                  (fdh->error_active))
420                {
421                   if (!fdh->func(fdh->data, fdh))
422                     {
423                        fdh->delete_me = 1;
424                        fd_handlers_delete_me = 1;
425                     }
426                   fdh->read_active = 0;
427                   fdh->write_active = 0;
428                   fdh->error_active = 0;
429                }
430           }
431      }
432 }
433
434 static int
435 _ecore_main_fd_handlers_buf_call(void)
436 {
437    Ecore_List2    *l;
438    int ret;
439
440    ret = 0;
441    for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
442      {
443         Ecore_Fd_Handler *fdh;
444
445         fdh = (Ecore_Fd_Handler *)l;
446         if (!fdh->delete_me)
447           {
448              if (fdh->buf_func)
449                {
450                   if (fdh->buf_func(fdh->buf_data, fdh))
451                     {
452                        ret |= fdh->func(fdh->data, fdh);
453                        fdh->read_active = 1;
454                     }
455                }
456           }
457      }
458    return ret;
459 }
460
461 static int
462 _ecore_main_win32_message(double timeout)
463 {
464 #ifdef _WIN32
465    MSG msg;
466
467    if (!finite(timeout))
468      timeout = 0.0;
469
470    if (timeout < 0.0)
471      {
472        for (;;)
473          {
474             if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
475               return 1;
476          }
477      }
478    else
479      {
480         double start;
481         double t;
482
483         start = ecore_time_get();
484         while ((t = ecore_time_get()) < (start + timeout))
485           {
486              if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
487                return 1;
488           }
489      }
490 #endif /* _WIN32 */
491
492    return 0;
493 }
494
495 static int
496 _ecore_main_win32_message_buf_call(void)
497 {
498 #ifdef _WIN32
499    MSG msg;
500    int ret;
501
502    ret = 0;
503    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
504      {
505         if ((msg.message & 0xffff) < 0xC000)
506           {
507              TranslateMessage(&msg);
508              DispatchMessage(&msg);
509           }
510         ret = 1;
511      }
512
513    return ret;
514 #else
515    return 0;
516 #endif /* _WIN32 */
517 }
518
519 static void
520 _ecore_main_loop_iterate_internal(int once_only)
521 {
522    double next_time;
523    int    have_event = 0;
524    int    have_signal;
525    int    have_msg = 0;
526
527    in_main_loop++;
528    /* expire any timers */
529      {
530         double now;
531
532         now = ecore_time_get();
533         while (_ecore_timer_call(now));
534         _ecore_timer_cleanup();
535      }
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())
541      {
542         have_event = 1;
543         have_signal = 1;
544         have_msg = 1;
545         _ecore_main_select(0.0);
546         _ecore_main_win32_message(0.0);
547         goto process_events;
548      }
549    /* call idle enterers ... */
550    if (!once_only)
551      _ecore_idle_enterer_call();
552    else
553      {
554         have_event = have_signal = have_msg = 0;
555
556         if (_ecore_main_select(0.0) > 0) have_event = 1;
557
558         if (_ecore_main_win32_message(0.0) > 0) have_msg = 1;
559         if (_ecore_signal_count_get() > 0) have_signal = 1;
560
561         if (have_signal || have_event || have_msg)
562           goto process_events;
563      }
564
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());
568
569    /* if ther are any - jump to processing them */
570    if (_ecore_event_exist())
571      {
572         have_event = 1;
573         have_signal = 1;
574         have_msg = 1;
575         _ecore_main_select(0.0);
576         _ecore_main_win32_message(0.0);
577         goto process_events;
578      }
579    if (once_only)
580      {
581         _ecore_idle_enterer_call();
582         in_main_loop--;
583         return;
584      }
585
586    if (_ecore_fps_debug)
587      {
588         t2 = ecore_time_get();
589         if ((t1 > 0.0) && (t2 > 0.0))
590           _ecore_fps_debug_runtime_add(t2 - t1);
591      }
592    start_loop:
593    if (do_quit)
594      {
595         in_main_loop--;
596         return;
597      }
598    if (!_ecore_event_exist())
599      {
600         /* init flags */
601         have_event = have_signal = have_msg = 0;
602         next_time = _ecore_timer_next_get();
603         /* no timers */
604         if (next_time < 0)
605           {
606              /* no idlers */
607              if (!_ecore_idler_exist())
608                {
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;
612                }
613              /* idlers */
614              else
615                {
616                   for (;;)
617                     {
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;
626                        if (do_quit) break;
627                     }
628                }
629           }
630         /* timers */
631         else
632           {
633              /* no idlers */
634              if (!_ecore_idler_exist())
635                {
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;
639                }
640              /* idlers */
641              else
642                {
643                   for (;;)
644                     {
645                        double cur_time, t;
646
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;
658                        if (do_quit) break;
659                     }
660                }
661           }
662      }
663    if (_ecore_fps_debug)
664      {
665         t1 = ecore_time_get();
666      }
667    /* we came out of our "wait state" so idle has exited */
668    if (!once_only)
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 */
673    process_events:
674    if (have_event) _ecore_main_fd_handlers_call();
675    do
676      {
677         /* process signals into events .... */
678         while (_ecore_signal_count_get()) _ecore_signal_call();
679         /* handle events ... */
680         _ecore_event_call();
681         _ecore_main_fd_handlers_cleanup();
682      }
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
689    if (once_only)
690  */
691      _ecore_idle_enterer_call();
692    in_main_loop--;
693 }