svn update: 48958 (latest:48959)
[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 # define WIN32_LEAN_AND_MEAN
11 # include <winsock2.h>
12 # undef WIN32_LEAN_AND_MEAN
13 # ifndef USER_TIMER_MINIMUM
14 #  define USER_TIMER_MINIMUM 0x0a
15 # endif
16 #endif
17
18 #ifdef __SUNPRO_C
19 # include <ieeefp.h>
20 # include <string.h>
21 #endif
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <math.h>
26 #include <sys/types.h>
27 #include <errno.h>
28 #include <fcntl.h>
29
30 #ifndef _MSC_VER
31 #include <sys/time.h>
32 # include <unistd.h>
33 #else
34 # include <float.h>
35 #endif
36
37 #define FIX_HZ 1
38
39 #ifdef FIX_HZ
40 # ifndef _MSC_VER
41 #  include <sys/param.h>
42 # endif
43 # ifndef HZ
44 #  define HZ 100
45 # endif
46 #endif
47
48 #ifdef HAVE_EVIL
49 # include <Evil.h>
50 #endif
51
52 #include "Ecore.h"
53 #include "ecore_private.h"
54
55
56 struct _Ecore_Fd_Handler
57 {
58    EINA_INLIST;
59    ECORE_MAGIC;
60    int                      fd;
61    Ecore_Fd_Handler_Flags   flags;
62    int                    (*func) (void *data, Ecore_Fd_Handler *fd_handler);
63    void                    *data;
64    int                    (*buf_func) (void *data, Ecore_Fd_Handler *fd_handler);
65    void                    *buf_data;
66    void                   (*prep_func) (void *data, Ecore_Fd_Handler *fd_handler);
67    void                    *prep_data;
68    int                      references;
69    Eina_Bool                read_active : 1;
70    Eina_Bool                write_active : 1;
71    Eina_Bool                error_active : 1;
72    Eina_Bool                delete_me : 1;
73 };
74
75 #ifdef _WIN32
76 struct _Ecore_Win32_Handler
77 {
78    EINA_INLIST;
79    ECORE_MAGIC;
80    HANDLE         h;
81    int          (*func) (void *data, Ecore_Win32_Handler *win32_handler);
82    void          *data;
83    int            references;
84    Eina_Bool      delete_me : 1;
85 };
86 #endif
87
88
89 static int  _ecore_main_select(double timeout);
90 static void _ecore_main_fd_handlers_cleanup(void);
91 #ifndef _WIN32
92 static void _ecore_main_fd_handlers_bads_rem(void);
93 #endif
94 static void _ecore_main_fd_handlers_call(void);
95 static int  _ecore_main_fd_handlers_buf_call(void);
96 static void _ecore_main_loop_iterate_internal(int once_only);
97
98 #ifdef _WIN32
99 static int _ecore_main_win32_select(int nfds, fd_set *readfds, fd_set *writefds,
100                                     fd_set *exceptfds, struct timeval *timeout);
101 static void _ecore_main_win32_handlers_cleanup(void);
102 #endif
103
104 static int               in_main_loop = 0;
105 static int               do_quit = 0;
106 static Ecore_Fd_Handler *fd_handlers = NULL;
107 static Ecore_Fd_Handler *fd_handler_current = NULL;
108 static int               fd_handlers_delete_me = 0;
109 #ifdef _WIN32
110 static Ecore_Win32_Handler *win32_handlers = NULL;
111 static Ecore_Win32_Handler *win32_handler_current = NULL;
112 static int                  win32_handlers_delete_me = 0;
113 #endif
114
115 #ifdef _WIN32
116 static int (*main_loop_select)(int , fd_set *, fd_set *, fd_set *, struct timeval *) = _ecore_main_win32_select;
117 #else
118 static int (*main_loop_select)(int , fd_set *, fd_set *, fd_set *, struct timeval *) = select;
119 #endif
120
121 static double            t1 = 0.0;
122 static double            t2 = 0.0;
123
124 /**
125  * @defgroup Ecore_Main_Loop_Group Main Loop Functions
126  *
127  * These functions control the Ecore event handling loop.  This loop is
128  * designed to work on embedded systems all the way to large and
129  * powerful mutli-cpu workstations.
130  *
131  * It serialises all system signals and events into a single event
132  * queue, that can be easily processed without needing to worry about
133  * concurrency.  A properly written, event-driven program using this
134  * kind of programming does not need threads.  It makes the program very
135  * robust and easy to follow.
136  *
137  * Here is an example of simple program and its basic event loop flow:
138  * @image html prog_flow.png
139  *
140  * For examples of setting up and using a main loop, see
141  * @ref event_handler_example.c and @ref timer_example.c.
142  */
143
144 /**
145  * Runs a single iteration of the main loop to process everything on the
146  * queue.
147  * @ingroup Ecore_Main_Loop_Group
148  */
149 EAPI void
150 ecore_main_loop_iterate(void)
151 {
152    _ecore_main_loop_iterate_internal(1);
153 }
154
155 /**
156  * Runs the application main loop.
157  *
158  * This function will not return until @ref ecore_main_loop_quit is called.
159  *
160  * @ingroup Ecore_Main_Loop_Group
161  */
162 EAPI void
163 ecore_main_loop_begin(void)
164 {
165    in_main_loop++;
166    for (;do_quit == 0;) _ecore_main_loop_iterate_internal(0);
167    do_quit = 0;
168    in_main_loop--;
169 }
170
171 /**
172  * Quits the main loop once all the events currently on the queue have
173  * been processed.
174  * @ingroup Ecore_Main_Loop_Group
175  */
176 EAPI void
177 ecore_main_loop_quit(void)
178 {
179    do_quit = 1;
180 }
181
182 /**
183  * Sets the function to use when monitoring multiple file descriptors,
184  * and waiting until one of more of the file descriptors before ready
185  * for some class of I/O operation.
186  *
187  * This function will be used instead of the system call select and
188  * could possible be used to integrate the Ecore event loop with an
189  * external event loop.
190  *
191  * @warning you don't know how to use, don't even try to use it.
192  *
193  * @ingroup Ecore_Main_Loop_Group
194  */
195 EAPI void
196 ecore_main_loop_select_func_set(int (*func)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout))
197 {
198    main_loop_select = func;
199 }
200
201 /**
202  * Gets the select function set by ecore_select_func_set(),
203  * or the native select function if none was set.
204  *
205  * @ingroup Ecore_Main_Loop_Group
206  */
207 EAPI void *
208 ecore_main_loop_select_func_get(void)
209 {
210    return main_loop_select;
211 }
212
213 /**
214  * @defgroup Ecore_FD_Handler_Group File Event Handling Functions
215  *
216  * Functions that deal with file descriptor handlers.
217  */
218
219 /**
220  * Adds a callback for activity on the given file descriptor.
221  *
222  * @p func will be called during the execution of @ref ecore_main_loop_begin
223  * when the file descriptor is available for reading, or writing, or both.
224  *
225  * Normally the return value from the @p func is "zero means this handler is
226  * finished and can be deleted" as is usual for handler callbacks.  However,
227  * if the @p buf_func is supplied, then the return value from the @p func is
228  * "non zero means the handler should be called again in a tight loop".
229  *
230  * @p buf_func is called during event loop handling to check if data that has
231  * been read from the file descriptor is in a buffer and is available to
232  * read.  Some systems (notably xlib) handle their own buffering, and would
233  * otherwise not work with select().  These systems should use a @p buf_func.
234  * This is a most annoying hack, only ecore_x uses it, so refer to that for
235  * an example.  NOTE - @p func should probably return "one" always if
236  * @p buf_func is used, to avoid confusion with the other return value
237  * semantics.
238  *
239  * @param   fd       The file descriptor to watch.
240  * @param   flags    To watch it for read (@c ECORE_FD_READ) and/or
241  *                   (@c ECORE_FD_WRITE) write ability.  @c ECORE_FD_ERROR
242  *
243  * @param   func     The callback function.
244  * @param   data     The data to pass to the callback.
245  * @param   buf_func The function to call to check if any data has been
246  *                   buffered and already read from the fd.  Can be @c NULL.
247  * @param   buf_data The data to pass to the @p buf_func function.
248  * @return  A fd handler handle if successful.  @c NULL otherwise.
249  * @ingroup Ecore_FD_Handler_Group
250  */
251 EAPI Ecore_Fd_Handler *
252 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)
253 {
254    Ecore_Fd_Handler *fdh;
255
256    if ((fd < 0) ||
257        (flags == 0) ||
258        (!func)) return NULL;
259
260    fdh = calloc(1, sizeof(Ecore_Fd_Handler));
261    if (!fdh) return NULL;
262    ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER);
263    fdh->fd = fd;
264    fdh->flags = flags;
265    fdh->read_active = 0;
266    fdh->write_active = 0;
267    fdh->error_active = 0;
268    fdh->delete_me = 0;
269    fdh->func = func;
270    fdh->data = (void *)data;
271    fdh->buf_func = buf_func;
272    fdh->buf_data = (void *)buf_data;
273    fd_handlers = (Ecore_Fd_Handler *) eina_inlist_append(EINA_INLIST_GET(fd_handlers),
274                                                          EINA_INLIST_GET(fdh));
275    return fdh;
276 }
277
278 #ifdef _WIN32
279 EAPI Ecore_Win32_Handler *
280 ecore_main_win32_handler_add(void *h,
281                              int (*func) (void *data, Ecore_Win32_Handler *wh),
282                              const void *data)
283 {
284    Ecore_Win32_Handler *wh;
285
286    if (!h || !func)
287      return NULL;
288
289    wh = calloc(1, sizeof(Ecore_Win32_Handler));
290    if (!wh) return NULL;
291    ECORE_MAGIC_SET(wh, ECORE_MAGIC_WIN32_HANDLER);
292    wh->h = (HANDLE)h;
293    wh->delete_me = 0;
294    wh->func = func;
295    wh->data = (void *)data;
296    win32_handlers = (Ecore_Win32_Handler *)eina_inlist_append(EINA_INLIST_GET(win32_handlers),
297                                                               EINA_INLIST_GET(wh));
298    return wh;
299 }
300 #else
301 EAPI Ecore_Win32_Handler *
302 ecore_main_win32_handler_add(void *h __UNUSED__,
303                              int (*func) (void *data, Ecore_Win32_Handler *wh) __UNUSED__,
304                              const void *data __UNUSED__)
305 {
306    return NULL;
307 }
308 #endif
309
310 /**
311  * Deletes the given FD handler.
312  * @param   fd_handler The given FD handler.
313  * @return  The data pointer set using @ref ecore_main_fd_handler_add,
314  *          for @p fd_handler on success.  @c NULL otherwise.
315  * @ingroup Ecore_FD_Handler_Group
316  */
317 EAPI void *
318 ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler)
319 {
320    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
321      {
322         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
323                          "ecore_main_fd_handler_del");
324         return NULL;
325      }
326    fd_handler->delete_me = 1;
327    fd_handlers_delete_me = 1;
328    return fd_handler->data;
329 }
330
331 #ifdef _WIN32
332 EAPI void *
333 ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler)
334 {
335    if (!ECORE_MAGIC_CHECK(win32_handler, ECORE_MAGIC_WIN32_HANDLER))
336      {
337         ECORE_MAGIC_FAIL(win32_handler, ECORE_MAGIC_WIN32_HANDLER,
338                          "ecore_main_win32_handler_del");
339         return NULL;
340      }
341    win32_handler->delete_me = 1;
342    win32_handlers_delete_me = 1;
343    return win32_handler->data;
344 }
345 #else
346 EAPI void *
347 ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler __UNUSED__)
348 {
349    return NULL;
350 }
351 #endif
352
353 EAPI void
354 ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler, void (*func) (void *data, Ecore_Fd_Handler *fd_handler), const void *data)
355 {
356    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
357      {
358         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
359                          "ecore_main_fd_handler_prepare_callback_set");
360         return;
361      }
362    fd_handler->prep_func = func;
363    fd_handler->prep_data = (void *) data;
364 }
365
366 /**
367  * Retrieves the file descriptor that the given handler is handling.
368  * @param   fd_handler The given FD handler.
369  * @return  The file descriptor the handler is watching.
370  * @ingroup Ecore_FD_Handler_Group
371  */
372 EAPI int
373 ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler)
374 {
375    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
376      {
377         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
378                          "ecore_main_fd_handler_fd_get");
379         return -1;
380      }
381    return fd_handler->fd;
382 }
383
384 /**
385  * Return if read, write or error, or a combination thereof, is active on the
386  * file descriptor of the given FD handler.
387  * @param   fd_handler The given FD handler.
388  * @param   flags      The flags, @c ECORE_FD_READ, @c ECORE_FD_WRITE or
389  *                     @c ECORE_FD_ERROR to query.
390  * @return  @c 1 if any of the given flags are active. @c 0 otherwise.
391  * @ingroup Ecore_FD_Handler_Group
392  */
393 EAPI int
394 ecore_main_fd_handler_active_get(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags)
395 {
396    int ret;
397
398    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
399      {
400         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
401                          "ecore_main_fd_handler_active_get");
402         return 0;
403      }
404    ret = 0;
405    if ((flags & ECORE_FD_READ) && (fd_handler->read_active)) ret = 1;
406    if ((flags & ECORE_FD_WRITE) && (fd_handler->write_active)) ret = 1;
407    if ((flags & ECORE_FD_ERROR) && (fd_handler->error_active)) ret = 1;
408    return ret;
409 }
410
411 /**
412  * Set what active streams the given FD handler should be monitoring.
413  * @param   fd_handler The given FD handler.
414  * @param   flags      The flags to be watching.
415  * @ingroup Ecore_FD_Handler_Group
416  */
417 EAPI void
418 ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags)
419 {
420    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
421      {
422         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
423                          "ecore_main_fd_handler_active_set");
424         return;
425      }
426    fd_handler->flags = flags;
427 }
428
429 void
430 _ecore_main_shutdown(void)
431 {
432    if (in_main_loop)
433      {
434        ERR("\n"
435            "*** ECORE WARINING: Calling ecore_shutdown() while still in the main loop.\n"
436            "***                 Program may crash or behave strangely now.");
437         return;
438      }
439    while (fd_handlers)
440      {
441         Ecore_Fd_Handler *fdh;
442
443         fdh = fd_handlers;
444         fd_handlers = (Ecore_Fd_Handler *) eina_inlist_remove(EINA_INLIST_GET(fd_handlers),
445                                                               EINA_INLIST_GET(fdh));
446         ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
447         free(fdh);
448      }
449    fd_handlers_delete_me = 0;
450    fd_handler_current = NULL;
451
452 #ifdef _WIN32
453    while (win32_handlers)
454      {
455         Ecore_Win32_Handler *wh;
456
457         wh = win32_handlers;
458         win32_handlers = (Ecore_Win32_Handler *) eina_inlist_remove(EINA_INLIST_GET(win32_handlers),
459                                                                     EINA_INLIST_GET(wh));
460         ECORE_MAGIC_SET(wh, ECORE_MAGIC_NONE);
461         free(wh);
462      }
463    win32_handlers_delete_me = 0;
464    win32_handler_current = NULL;
465 #endif
466 }
467
468 static int
469 _ecore_main_select(double timeout)
470 {
471    struct timeval tv, *t;
472    fd_set         rfds, wfds, exfds;
473    int            max_fd;
474    int            ret;
475    Ecore_Fd_Handler *fdh;
476
477    t = NULL;
478    if ((!finite(timeout)) || (timeout == 0.0))  /* finite() tests for NaN, too big, too small, and infinity.  */
479      {
480         tv.tv_sec = 0;
481         tv.tv_usec = 0;
482         t = &tv;
483      }
484    else if (timeout > 0.0)
485      {
486         int sec, usec;
487
488 #ifdef FIX_HZ
489         timeout += (0.5 / HZ);
490         sec = (int)timeout;
491         usec = (int)((timeout - (double)sec) * 1000000);
492 #else
493         sec = (int)timeout;
494         usec = (int)((timeout - (double)sec) * 1000000);
495 #endif
496         tv.tv_sec = sec;
497         tv.tv_usec = usec;
498         t = &tv;
499      }
500    max_fd = 0;
501    FD_ZERO(&rfds);
502    FD_ZERO(&wfds);
503    FD_ZERO(&exfds);
504
505    /* call the prepare callback for all handlers */
506    EINA_INLIST_FOREACH(fd_handlers, fdh)
507      if (!fdh->delete_me && fdh->prep_func)
508        {
509           fdh->references++;
510           fdh->prep_func (fdh->prep_data, fdh);
511           fdh->references--;
512        }
513    EINA_INLIST_FOREACH(fd_handlers, fdh)
514      if (!fdh->delete_me)
515        {
516           if (fdh->flags & ECORE_FD_READ)
517             {
518                FD_SET(fdh->fd, &rfds);
519                if (fdh->fd > max_fd) max_fd = fdh->fd;
520             }
521           if (fdh->flags & ECORE_FD_WRITE)
522             {
523                FD_SET(fdh->fd, &wfds);
524                if (fdh->fd > max_fd) max_fd = fdh->fd;
525             }
526           if (fdh->flags & ECORE_FD_ERROR)
527             {
528                FD_SET(fdh->fd, &exfds);
529                if (fdh->fd > max_fd) max_fd = fdh->fd;
530             }
531        }
532    if (_ecore_signal_count_get()) return -1;
533
534    ret = main_loop_select(max_fd + 1, &rfds, &wfds, &exfds, t);
535
536    _ecore_loop_time = ecore_time_get();
537    if (ret < 0)
538      {
539 #ifndef _WIN32
540         if (errno == EINTR) return -1;
541         else if (errno == EBADF)
542           _ecore_main_fd_handlers_bads_rem();
543 #endif
544      }
545    if (ret > 0)
546      {
547         EINA_INLIST_FOREACH(fd_handlers, fdh)
548           if (!fdh->delete_me)
549             {
550                if (FD_ISSET(fdh->fd, &rfds))
551                  fdh->read_active = 1;
552                if (FD_ISSET(fdh->fd, &wfds))
553                  fdh->write_active = 1;
554                if (FD_ISSET(fdh->fd, &exfds))
555                  fdh->error_active = 1;
556             }
557         _ecore_main_fd_handlers_cleanup();
558 #ifdef _WIN32
559         _ecore_main_win32_handlers_cleanup();
560 #endif
561         return 1;
562      }
563    return 0;
564 }
565
566 #ifndef _WIN32
567 static void
568 _ecore_main_fd_handlers_bads_rem(void)
569 {
570    Ecore_Fd_Handler *fdh;
571    Eina_Inlist *l;
572    int found = 0;
573
574    ERR("Removing bad fds");
575    for (l = EINA_INLIST_GET(fd_handlers); l; )
576      {
577         fdh = (Ecore_Fd_Handler *) l;
578         l = l->next;
579         errno = 0;
580
581         if ((fcntl(fdh->fd, F_GETFD) < 0) && (errno == EBADF))
582           {
583              ERR("Found bad fd at index %d", fdh->fd);
584              if (fdh->flags & ECORE_FD_ERROR)
585                {
586                   ERR("Fd set for error! calling user");
587                   fdh->references++;
588                   if (!fdh->func(fdh->data, fdh))
589                     {
590                        ERR("Fd function err returned 0, remove it");
591                        fdh->delete_me = 1;
592                        fd_handlers_delete_me = 1;
593                        found++;
594                     }
595                   fdh->references--;
596                }
597              else
598                {
599                   ERR("Problematic fd found at %d! setting it for delete", fdh->fd);
600                   fdh->delete_me = 1;
601                   fd_handlers_delete_me = 1;
602                   found++;
603                }
604           }
605     }
606    if (found == 0)
607      {
608 #ifdef HAVE_GLIB
609         ERR("No bad fd found. Maybe a foreign fd from glib?");
610 #else        
611         ERR("No bad fd found. EEEK!");
612 #endif        
613      }
614    _ecore_main_fd_handlers_cleanup();
615 }
616 #endif
617
618 static void
619 _ecore_main_fd_handlers_cleanup(void)
620 {
621    Ecore_Fd_Handler *fdh;
622    Eina_Inlist *l;
623    int deleted_in_use = 0;
624
625    if (!fd_handlers_delete_me) return;
626    for (l = EINA_INLIST_GET(fd_handlers); l; )
627      {
628         fdh = (Ecore_Fd_Handler *) l;
629
630         l = l->next;
631         if (fdh->delete_me)
632           {
633 //           ERR("Removing fd %d", fdh->fd);
634
635              if (fdh->references)
636                {
637                   deleted_in_use++;
638                   continue;
639                }
640
641              fd_handlers = (Ecore_Fd_Handler *) eina_inlist_remove(EINA_INLIST_GET(fd_handlers),
642                                                                    EINA_INLIST_GET(fdh));
643              ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
644              free(fdh);
645           }
646      }
647    if (!deleted_in_use)
648      fd_handlers_delete_me = 0;
649 }
650
651 #ifdef _WIN32
652 static void
653 _ecore_main_win32_handlers_cleanup(void)
654 {
655    Ecore_Win32_Handler *wh;
656    Eina_Inlist *l;
657    int deleted_in_use = 0;
658
659    if (!win32_handlers_delete_me) return;
660    for (l = EINA_INLIST_GET(win32_handlers); l; )
661      {
662         wh = (Ecore_Win32_Handler *)l;
663
664         l = l->next;
665         if (wh->delete_me)
666           {
667              if (wh->references)
668                {
669                   deleted_in_use++;
670                   continue;
671                }
672
673              win32_handlers = (Ecore_Win32_Handler *)eina_inlist_remove(EINA_INLIST_GET(win32_handlers),
674                                                                         EINA_INLIST_GET(wh));
675              ECORE_MAGIC_SET(wh, ECORE_MAGIC_NONE);
676              free(wh);
677           }
678      }
679    if (!deleted_in_use)
680      win32_handlers_delete_me = 0;
681 }
682 #endif
683
684 static void
685 _ecore_main_fd_handlers_call(void)
686 {
687    if (!fd_handler_current)
688      {
689         /* regular main loop, start from head */
690         fd_handler_current = fd_handlers;
691      }
692    else
693      {
694         /* recursive main loop, continue from where we were */
695         fd_handler_current = (Ecore_Fd_Handler *)EINA_INLIST_GET(fd_handler_current)->next;
696      }
697
698    while (fd_handler_current)
699      {
700         Ecore_Fd_Handler *fdh = fd_handler_current;
701
702         if (!fdh->delete_me)
703           {
704              if ((fdh->read_active) ||
705                  (fdh->write_active) ||
706                  (fdh->error_active))
707                {
708                   fdh->references++;
709                   if (!fdh->func(fdh->data, fdh))
710                     {
711                        fdh->delete_me = 1;
712                        fd_handlers_delete_me = 1;
713                     }
714                   fdh->references--;
715
716                   fdh->read_active = 0;
717                   fdh->write_active = 0;
718                   fdh->error_active = 0;
719                }
720           }
721
722         if (fd_handler_current) /* may have changed in recursive main loops */
723           fd_handler_current = (Ecore_Fd_Handler *)EINA_INLIST_GET(fd_handler_current)->next;
724      }
725 }
726
727 static int
728 _ecore_main_fd_handlers_buf_call(void)
729 {
730    Ecore_Fd_Handler *fdh;
731    int ret;
732
733    ret = 0;
734    EINA_INLIST_FOREACH(fd_handlers, fdh)
735      if (!fdh->delete_me)
736        {
737           if (fdh->buf_func)
738             {
739                fdh->references++;
740                if (fdh->buf_func(fdh->buf_data, fdh))
741                  {
742                     ret |= fdh->func(fdh->data, fdh);
743                     fdh->read_active = 1;
744                  }
745                fdh->references--;
746             }
747        }
748
749    return ret;
750 }
751
752 static void
753 _ecore_main_loop_iterate_internal(int once_only)
754 {
755    double next_time = -1.0;
756    int    have_event = 0;
757    int    have_signal;
758
759    in_main_loop++;
760    /* expire any timers */
761    while (_ecore_timer_call(_ecore_loop_time));
762    _ecore_timer_cleanup();
763
764    /* process signals into events .... */
765    while (_ecore_signal_count_get()) _ecore_signal_call();
766    if (_ecore_event_exist())
767      {
768         _ecore_idle_enterer_call();
769         have_event = 1;
770         _ecore_main_select(0.0);
771         _ecore_loop_time = ecore_time_get();
772         _ecore_timer_enable_new();
773         goto process_events;
774      }
775    /* call idle enterers ... */
776    if (!once_only) _ecore_idle_enterer_call();
777    else
778      {
779         have_event = have_signal = 0;
780
781         if (_ecore_main_select(0.0) > 0) have_event = 1;
782         if (_ecore_signal_count_get() > 0) have_signal = 1;
783         if (have_signal || have_event)
784           {
785              _ecore_loop_time = ecore_time_get();
786              _ecore_timer_enable_new();
787              goto process_events;
788           }
789      }
790
791    /* if these calls caused any buffered events to appear - deal with them */
792    _ecore_main_fd_handlers_buf_call();
793
794    /* if ther are any - jump to processing them */
795    if (_ecore_event_exist())
796      {
797         have_event = 1;
798         _ecore_main_select(0.0);
799         _ecore_loop_time = ecore_time_get();
800         _ecore_timer_enable_new();
801         goto process_events;
802      }
803    if (once_only)
804      {
805         _ecore_idle_enterer_call();
806         in_main_loop--;
807         _ecore_loop_time = ecore_time_get();
808         _ecore_timer_enable_new();
809         return;
810      }
811
812    if (_ecore_fps_debug)
813      {
814         t2 = ecore_time_get();
815         if ((t1 > 0.0) && (t2 > 0.0))
816           _ecore_fps_debug_runtime_add(t2 - t1);
817      }
818    start_loop:
819    /* any timers re-added as a result of these are allowed to go */
820    _ecore_timer_enable_new();
821    if (do_quit)
822      {
823         _ecore_loop_time = ecore_time_get();
824         in_main_loop--;
825         _ecore_timer_enable_new();
826         return;
827      }
828    if (!_ecore_event_exist())
829      {
830         /* init flags */
831         have_event = have_signal = 0;
832         next_time = _ecore_timer_next_get();
833         /* no timers */
834         if (next_time < 0)
835           {
836              /* no idlers */
837              if (!_ecore_idler_exist())
838                {
839                   if (_ecore_main_select(-1.0) > 0) have_event = 1;
840                }
841              /* idlers */
842              else
843                {
844                   for (;;)
845                     {
846                        if (!_ecore_idler_call()) goto start_loop;
847                        if (_ecore_event_exist()) break;
848                        if (_ecore_main_select(0.0) > 0) have_event = 1;
849                        if (_ecore_signal_count_get() > 0) have_signal = 1;
850                        if (have_event || have_signal) break;
851                        if (_ecore_timers_exists()) goto start_loop;
852                        if (do_quit) break;
853                     }
854                }
855           }
856         /* timers */
857         else
858           {
859              /* no idlers */
860              if (!_ecore_idler_exist())
861                {
862                   if (_ecore_main_select(next_time) > 0) have_event = 1;
863                }
864              /* idlers */
865              else
866                {
867                   for (;;)
868                     {
869                        if (!_ecore_idler_call()) goto start_loop;
870                        if (_ecore_event_exist()) break;
871                        if (_ecore_main_select(0.0) > 0) have_event = 1;
872                        if (_ecore_signal_count_get() > 0) have_signal = 1;
873                        if (have_event || have_signal) break;
874                        next_time = _ecore_timer_next_get();
875                        if (next_time <= 0) break;
876                        if (do_quit) break;
877                     }
878                }
879           }
880         _ecore_loop_time = ecore_time_get();
881      }
882    if (_ecore_fps_debug)
883      {
884         t1 = ecore_time_get();
885      }
886    /* we came out of our "wait state" so idle has exited */
887    if (!once_only)
888      _ecore_idle_exiter_call();
889    /* call the fd handler per fd that became alive... */
890    /* this should read or write any data to the monitored fd and then */
891    /* post events onto the ecore event pipe if necessary */
892    process_events:
893 //   if (have_event) 
894    _ecore_main_fd_handlers_call();
895    _ecore_main_fd_handlers_buf_call();
896 //   do
897 //     {
898         /* process signals into events .... */
899         while (_ecore_signal_count_get()) _ecore_signal_call();
900         /* handle events ... */
901         _ecore_event_call();
902         _ecore_main_fd_handlers_cleanup();
903 //     }
904 //   while (_ecore_main_fd_handlers_buf_call());
905
906 /* ok - too much optimising. let's call idle enterers more often. if we
907  * have events that place more events or jobs etc. on the event queue
908  * we may never get to call an idle enterer
909    if (once_only)
910  */
911    if (once_only)
912      _ecore_idle_enterer_call();
913    in_main_loop--;
914 }
915
916 #ifdef _WIN32
917 static int
918 _ecore_main_win32_select(int nfds __UNUSED__, fd_set *readfds, fd_set *writefds,
919                          fd_set *exceptfds, struct timeval *tv)
920 {
921    HANDLE objects[MAXIMUM_WAIT_OBJECTS];
922    int    sockets[MAXIMUM_WAIT_OBJECTS];
923    Ecore_Fd_Handler *fdh;
924    Ecore_Win32_Handler *wh;
925    unsigned int objects_nbr = 0;
926    unsigned int handles_nbr = 0;
927    unsigned int events_nbr = 0;
928    DWORD  result;
929    DWORD  timeout;
930    MSG    msg;
931    unsigned int    i;
932    int    res;
933
934    /* Create an event object per socket */
935    EINA_INLIST_FOREACH(fd_handlers, fdh)
936      {
937         WSAEVENT event;
938         long network_event;
939
940         network_event = 0;
941         if(FD_ISSET(fdh->fd, readfds))
942           network_event |= FD_READ;
943         if(FD_ISSET(fdh->fd, writefds))
944           network_event |= FD_WRITE;
945         if(FD_ISSET(fdh->fd, exceptfds))
946           network_event |= FD_OOB;
947
948         if(network_event)
949           {
950              event = WSACreateEvent();
951              WSAEventSelect(fdh->fd, event, network_event);
952              objects[objects_nbr] = event;
953              sockets[events_nbr] = fdh->fd;
954              events_nbr++;
955              objects_nbr++;
956           }
957      }
958
959    /* store the HANDLEs in the objects to wait for */
960    EINA_INLIST_FOREACH(win32_handlers, wh)
961      {
962         objects[objects_nbr] = wh->h;
963         handles_nbr++;
964         objects_nbr++;
965      }
966
967    /* Empty the queue before waiting */
968    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
969      {
970         TranslateMessage(&msg);
971         DispatchMessage(&msg);
972      }
973
974    /* Wait for any message sent or posted to this queue */
975    /* or for one of the passed handles be set to signaled. */
976    if(tv == NULL)
977      timeout = INFINITE;
978    else
979      timeout = (DWORD)(tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0);
980
981    if (timeout == 0) return 0;
982
983    result = MsgWaitForMultipleObjects(objects_nbr, (const HANDLE *)objects, EINA_FALSE,
984                                       timeout, QS_ALLINPUT);
985
986    FD_ZERO(readfds);
987    FD_ZERO(writefds);
988    FD_ZERO(exceptfds);
989
990    /* The result tells us the type of event we have. */
991    if (result == WAIT_FAILED)
992      {
993         char *msg;
994
995         msg = evil_last_error_get();
996         ERR(" * %s\n", msg);
997         free(msg);
998         res = -1;
999      }
1000    else if (result == WAIT_TIMEOUT)
1001      {
1002         ERR("time out\n");
1003         res = 0;
1004      }
1005    else if (result == (WAIT_OBJECT_0 + objects_nbr))
1006      {
1007         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
1008           {
1009              TranslateMessage(&msg);
1010              DispatchMessage(&msg);
1011           }
1012
1013         res = 0;
1014      }
1015    else if ((result >= 0) && (result < WAIT_OBJECT_0 + events_nbr))
1016      {
1017         WSANETWORKEVENTS network_event;
1018
1019         WSAEnumNetworkEvents(sockets[result], objects[result], &network_event);
1020
1021         if(network_event.lNetworkEvents & FD_READ)
1022           FD_SET(sockets[result], readfds);
1023         if(network_event.lNetworkEvents & FD_WRITE)
1024           FD_SET(sockets[result], writefds);
1025         if(network_event.lNetworkEvents & FD_OOB)
1026           FD_SET(sockets[result], exceptfds);
1027
1028         res = 1;
1029      }
1030    else if ((result >= WAIT_OBJECT_0 + events_nbr) && (result < WAIT_OBJECT_0 + objects_nbr))
1031      {
1032         if (!win32_handler_current)
1033           {
1034              /* regular main loop, start from head */
1035              win32_handler_current = win32_handlers;
1036           }
1037         else
1038           {
1039              /* recursive main loop, continue from where we were */
1040              win32_handler_current = (Ecore_Win32_Handler *)EINA_INLIST_GET(win32_handler_current)->next;
1041           }
1042
1043         while (win32_handler_current)
1044           {
1045              wh = win32_handler_current;
1046
1047              if (objects[result - WAIT_OBJECT_0] == wh->h)
1048                if (!wh->delete_me)
1049                  {
1050                     wh->references++;
1051                     if (!wh->func(wh->data, wh))
1052                       {
1053                          wh->delete_me = 1;
1054                          win32_handlers_delete_me = 1;
1055                       }
1056                     wh->references--;
1057                  }
1058
1059              if (win32_handler_current) /* may have changed in recursive main loops */
1060                win32_handler_current = (Ecore_Win32_Handler *)EINA_INLIST_GET(win32_handler_current)->next;
1061           }
1062         res = 1;
1063      }
1064    else
1065      {
1066         ERR("unknown result...\n");
1067         res = -1;
1068      }
1069
1070    /* Remove event objects again */
1071    for(i = 0; i < events_nbr; i++)
1072      WSACloseEvent(objects[i]);
1073
1074    return res;
1075 }
1076 #endif