Remove widechar tests and defines. (fd_set): Change the grep for `fd_mask'
[platform/upstream/glib.git] / gmain.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * gmain.c: Main loop abstraction, timeouts, and idle functions
5  * Copyright 1998 Owen Taylor
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /*
24  * Modified by the GLib Team and others 1997-1999.  See the AUTHORS
25  * file for a list of people on the GLib Team.  See the ChangeLog
26  * files for a list of changes.  These files are distributed with
27  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
28  */
29
30 /* 
31  * MT safe
32  */
33
34 #include "config.h"
35
36 #include "glib.h"
37 #include <sys/types.h>
38 #include <time.h>
39 #ifdef HAVE_SYS_TIME_H
40 #include <sys/time.h>
41 #endif /* HAVE_SYS_TIME_H */
42 #ifdef GLIB_HAVE_SYS_POLL_H
43 #  include <sys/poll.h>
44 #  undef events  /* AIX 4.1.5 & 4.3.2 define this for SVR3,4 compatibility */
45 #  undef revents /* AIX 4.1.5 & 4.3.2 define this for SVR3,4 compatibility */
46 #endif /* GLIB_HAVE_SYS_POLL_H */
47 #ifdef HAVE_UNISTD_H
48 #include <unistd.h>
49 #endif /* HAVE_UNISTD_H */
50 #include <errno.h>
51
52 #ifdef NATIVE_WIN32
53 #define STRICT
54 #include <windows.h>
55 #endif /* NATIVE_WIN32 */
56
57 #ifdef _MSC_VER
58 #include <fcntl.h>
59 #include <io.h>
60 #endif /* _MSC_VER */
61
62 /* Types */
63
64 typedef struct _GTimeoutData GTimeoutData;
65 typedef struct _GSource GSource;
66 typedef struct _GPollRec GPollRec;
67
68 typedef enum
69 {
70   G_SOURCE_READY = 1 << G_HOOK_FLAG_USER_SHIFT,
71   G_SOURCE_CAN_RECURSE = 1 << (G_HOOK_FLAG_USER_SHIFT + 1)
72 } GSourceFlags;
73
74 struct _GSource
75 {
76   GHook hook;
77   gint priority;
78   gpointer source_data;
79 };
80
81 struct _GMainLoop
82 {
83   gboolean is_running;
84 };
85
86 struct _GTimeoutData
87 {
88   GTimeVal    expiration;
89   gint        interval;
90   GSourceFunc callback;
91 };
92
93 struct _GPollRec
94 {
95   gint priority;
96   GPollFD *fd;
97   GPollRec *next;
98 };
99
100 /* Forward declarations */
101
102 static gint     g_source_compare          (GHook      *a,
103                                            GHook      *b);
104 static void     g_source_destroy_func     (GHookList  *hook_list,
105                                            GHook      *hook);
106 static void     g_main_poll               (gint      timeout,
107                                            gboolean  use_priority, 
108                                            gint      priority);
109 static void     g_main_add_poll_unlocked  (gint      priority,
110                                            GPollFD  *fd);
111
112 static gboolean g_timeout_prepare      (gpointer  source_data, 
113                                         GTimeVal *current_time,
114                                         gint     *timeout);
115 static gboolean g_timeout_check        (gpointer  source_data,
116                                         GTimeVal *current_time);
117 static gboolean g_timeout_dispatch     (gpointer  source_data,
118                                         GTimeVal *current_time,
119                                         gpointer  user_data);
120 static gboolean g_idle_prepare         (gpointer  source_data, 
121                                         GTimeVal *current_time,
122                                         gint     *timeout);
123 static gboolean g_idle_check           (gpointer  source_data,
124                                         GTimeVal *current_time);
125 static gboolean g_idle_dispatch        (gpointer  source_data,
126                                         GTimeVal *current_time,
127                                         gpointer  user_data);
128
129 /* Data */
130
131 static GSList *pending_dispatches = NULL;
132 static GHookList source_list = { 0 };
133 static gint in_check_or_prepare = 0;
134
135 /* The following lock is used for both the list of sources
136  * and the list of poll records
137  */
138 G_LOCK_DEFINE_STATIC (main_loop);
139
140 static GSourceFuncs timeout_funcs =
141 {
142   g_timeout_prepare,
143   g_timeout_check,
144   g_timeout_dispatch,
145   g_free,
146 };
147
148 static GSourceFuncs idle_funcs =
149 {
150   g_idle_prepare,
151   g_idle_check,
152   g_idle_dispatch,
153   NULL,
154 };
155
156 static GPollRec *poll_records = NULL;
157 static GPollRec *poll_free_list = NULL;
158 static GMemChunk *poll_chunk;
159 static guint n_poll_records = 0;
160
161 #ifdef G_THREADS_ENABLED
162 #ifndef NATIVE_WIN32
163 /* this pipe is used to wake up the main loop when a source is added.
164  */
165 static gint wake_up_pipe[2] = { -1, -1 };
166 #else /* NATIVE_WIN32 */
167 static HANDLE wake_up_semaphore = NULL;
168 #endif /* NATIVE_WIN32 */
169 static GPollFD wake_up_rec;
170 static gboolean poll_waiting = FALSE;
171 #endif /* G_THREADS_ENABLED */
172
173 #ifdef HAVE_POLL
174 static GPollFunc poll_func = (GPollFunc) poll;
175 #else   /* !HAVE_POLL */
176 #ifdef NATIVE_WIN32
177
178 static gint
179 g_poll (GPollFD *fds, guint nfds, gint timeout)
180 {
181   HANDLE handles[MAXIMUM_WAIT_OBJECTS];
182   GPollFD *f;
183   DWORD ready;
184   MSG msg;
185   UINT timer;
186   LONG prevcnt;
187   gint poll_msgs = -1;
188   gint nhandles = 0;
189
190   for (f = fds; f < &fds[nfds]; ++f)
191     if (f->fd >= 0)
192       {
193         if (f->events & G_IO_IN)
194           if (f->fd == G_WIN32_MSG_HANDLE)
195             poll_msgs = f - fds;
196           else
197             {
198               /* g_print ("g_poll: waiting for handle %#x\n", f->fd); */
199               handles[nhandles++] = (HANDLE) f->fd;
200             }
201       }
202
203   if (timeout == -1)
204     timeout = INFINITE;
205
206   if (poll_msgs >= 0)
207     {
208       /* Waiting for messages, and maybe events */
209       if (nhandles == 0)
210         {
211           if (timeout == INFINITE)
212             {
213               /* Waiting just for messages, infinite timeout
214                * -> Use PeekMessage, then WaitMessage
215                */
216               /* g_print ("WaitMessage, PeekMessage\n"); */
217               if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
218                 ready = WAIT_OBJECT_0;
219               else if (!WaitMessage ())
220                 g_warning ("g_poll: WaitMessage failed");
221               ready = WAIT_OBJECT_0;
222             }
223           else if (timeout == 0)
224             {
225               /* Waiting just for messages, zero timeout
226                * -> Use PeekMessage
227                */
228               /* g_print ("PeekMessage\n"); */
229               if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
230                 ready = WAIT_OBJECT_0;
231               else
232                 ready = WAIT_TIMEOUT;
233             }
234           else
235             {
236               /* Waiting just for messages, some timeout
237                * -> First try PeekMessage, then set a timer, wait for message,
238                * kill timer, use PeekMessage
239                */
240               /* g_print ("PeekMessage\n"); */
241               if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
242                 ready = WAIT_OBJECT_0;
243               else if ((timer = SetTimer (NULL, 0, timeout, NULL)) == 0)
244                 g_warning ("g_poll: SetTimer failed");
245               else
246                 {
247                   /* g_print ("WaitMessage\n"); */
248                   WaitMessage ();
249                   KillTimer (NULL, timer);
250                   if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
251                     ready = WAIT_OBJECT_0;
252                   else
253                     ready = WAIT_TIMEOUT;
254                 }
255             }
256         }
257       else
258         {
259           /* Wait for either message or event
260            * -> Use MsgWaitForMultipleObjects
261            */
262           /* g_print ("MsgWaitForMultipleObjects(%d, %d)\n", nhandles, timeout); */
263           ready = MsgWaitForMultipleObjects (nhandles, handles, FALSE,
264                                              timeout, QS_ALLINPUT);
265           /* g_print("=%d\n", ready); */
266           if (ready == WAIT_FAILED)
267             g_warning ("g_poll: MsgWaitForMultipleObjects failed");
268         }
269     }
270   else if (nhandles == 0)
271     {
272       /* Wait for nothing (huh?) */
273       return 0;
274     }
275   else
276     {
277       /* Wait for just events
278        * -> Use WaitForMultipleObjects
279        */
280       /* g_print ("WaitForMultipleObjects(%d, %d)\n", nhandles, timeout); */
281       ready = WaitForMultipleObjects (nhandles, handles, FALSE, timeout);
282       /* g_print("=%d\n", ready); */
283       if (ready == WAIT_FAILED)
284         g_warning ("g_poll: WaitForMultipleObjects failed");
285     }
286
287   for (f = fds; f < &fds[nfds]; ++f)
288     f->revents = 0;
289
290   if (ready == WAIT_FAILED)
291     return -1;
292   else if (poll_msgs >= 0 && ready == WAIT_OBJECT_0 + nhandles)
293     {
294       fds[poll_msgs].revents |= G_IO_IN;
295     }
296   else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)
297     for (f = fds; f < &fds[nfds]; ++f)
298       {
299         if ((f->events & G_IO_IN)
300             && f->fd == (gint) handles[ready - WAIT_OBJECT_0])
301           {
302             f->revents |= G_IO_IN;
303             /* g_print ("event %#x\n", f->fd); */
304             ResetEvent ((HANDLE) f->fd);
305           }
306       }
307     
308   if (ready == WAIT_TIMEOUT)
309     return 0;
310   else
311     return 1;
312 }
313
314 #else  /* !NATIVE_WIN32 */
315
316 /* The following implementation of poll() comes from the GNU C Library.
317  * Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
318  */
319
320 #include <string.h> /* for bzero on BSD systems */
321
322 #ifdef HAVE_SYS_SELECT_H
323 #include <sys/select.h>
324 #endif /* HAVE_SYS_SELECT_H */
325
326 #ifndef NO_FD_SET
327 #  define SELECT_MASK fd_set
328 #else /* !NO_FD_SET */
329 #  ifdef _IBMR2
330 #    define SELECT_MASK void
331 #  else /* !_IBMR2 */
332 #    define SELECT_MASK int
333 #  endif /* !_IBMR2 */
334 #endif /* !NO_FD_SET */
335
336 static gint 
337 g_poll (GPollFD *fds,
338         guint    nfds,
339         gint     timeout)
340 {
341   struct timeval tv;
342   SELECT_MASK rset, wset, xset;
343   GPollFD *f;
344   int ready;
345   int maxfd = 0;
346
347   FD_ZERO (&rset);
348   FD_ZERO (&wset);
349   FD_ZERO (&xset);
350
351   for (f = fds; f < &fds[nfds]; ++f)
352     if (f->fd >= 0)
353       {
354         if (f->events & G_IO_IN)
355           FD_SET (f->fd, &rset);
356         if (f->events & G_IO_OUT)
357           FD_SET (f->fd, &wset);
358         if (f->events & G_IO_PRI)
359           FD_SET (f->fd, &xset);
360         if (f->fd > maxfd && (f->events & (G_IO_IN|G_IO_OUT|G_IO_PRI)))
361           maxfd = f->fd;
362       }
363
364   tv.tv_sec = timeout / 1000;
365   tv.tv_usec = (timeout % 1000) * 1000;
366
367   ready = select (maxfd + 1, &rset, &wset, &xset,
368                   timeout == -1 ? NULL : &tv);
369   if (ready > 0)
370     for (f = fds; f < &fds[nfds]; ++f)
371       {
372         f->revents = 0;
373         if (f->fd >= 0)
374           {
375             if (FD_ISSET (f->fd, &rset))
376               f->revents |= G_IO_IN;
377             if (FD_ISSET (f->fd, &wset))
378               f->revents |= G_IO_OUT;
379             if (FD_ISSET (f->fd, &xset))
380               f->revents |= G_IO_PRI;
381           }
382       }
383
384   return ready;
385 }
386
387 #endif /* !NATIVE_WIN32 */
388
389 static GPollFunc poll_func = g_poll;
390 #endif  /* !HAVE_POLL */
391
392 /* Hooks for adding to the main loop */
393
394 /* Use knowledge of insert_sorted algorithm here to make
395  * sure we insert at the end of equal priority items
396  */
397 static gint
398 g_source_compare (GHook *a,
399                   GHook *b)
400 {
401   GSource *source_a = (GSource *)a;
402   GSource *source_b = (GSource *)b;
403
404   return (source_a->priority < source_b->priority) ? -1 : 1;
405 }
406
407 /* HOLDS: main_loop lock */
408 static void
409 g_source_destroy_func (GHookList *hook_list,
410                        GHook     *hook)
411 {
412   GSource *source = (GSource*) hook;
413   GDestroyNotify destroy;
414
415   G_UNLOCK (main_loop);
416
417   destroy = hook->destroy;
418   if (destroy)
419     destroy (hook->data);
420
421   destroy = ((GSourceFuncs*) hook->func)->destroy;
422   if (destroy)
423     destroy (source->source_data);
424
425   G_LOCK (main_loop);
426 }
427
428 guint 
429 g_source_add (gint           priority,
430               gboolean       can_recurse,
431               GSourceFuncs  *funcs,
432               gpointer       source_data, 
433               gpointer       user_data,
434               GDestroyNotify notify)
435 {
436   guint return_val;
437   GSource *source;
438
439   G_LOCK (main_loop);
440
441   if (!source_list.is_setup)
442     {
443       g_hook_list_init (&source_list, sizeof (GSource));
444
445       source_list.hook_destroy = G_HOOK_DEFERRED_DESTROY;
446       source_list.hook_free = g_source_destroy_func;
447     }
448
449   source = (GSource*) g_hook_alloc (&source_list);
450   source->priority = priority;
451   source->source_data = source_data;
452   source->hook.func = funcs;
453   source->hook.data = user_data;
454   source->hook.destroy = notify;
455   
456   g_hook_insert_sorted (&source_list, 
457                         (GHook *)source, 
458                         g_source_compare);
459
460   if (can_recurse)
461     source->hook.flags |= G_SOURCE_CAN_RECURSE;
462
463   return_val = source->hook.hook_id;
464
465 #ifdef G_THREADS_ENABLED
466   /* Now wake up the main loop if it is waiting in the poll() */
467
468   if (poll_waiting)
469     {
470       poll_waiting = FALSE;
471 #ifndef NATIVE_WIN32
472       write (wake_up_pipe[1], "A", 1);
473 #else
474       ReleaseSemaphore (wake_up_semaphore, 1, NULL);
475 #endif
476     }
477 #endif
478   G_UNLOCK (main_loop);
479
480   return return_val;
481 }
482
483 gboolean
484 g_source_remove (guint tag)
485 {
486   GHook *hook;
487
488   g_return_val_if_fail (tag > 0, FALSE);
489
490   G_LOCK (main_loop);
491
492   hook = g_hook_get (&source_list, tag);
493   if (hook)
494     g_hook_destroy_link (&source_list, hook);
495
496   G_UNLOCK (main_loop);
497
498   return hook != NULL;
499 }
500
501 gboolean
502 g_source_remove_by_user_data (gpointer user_data)
503 {
504   GHook *hook;
505   
506   G_LOCK (main_loop);
507   
508   hook = g_hook_find_data (&source_list, TRUE, user_data);
509   if (hook)
510     g_hook_destroy_link (&source_list, hook);
511
512   G_UNLOCK (main_loop);
513
514   return hook != NULL;
515 }
516
517 static gboolean
518 g_source_find_source_data (GHook        *hook,
519                            gpointer      data)
520 {
521   GSource *source = (GSource *)hook;
522
523   return (source->source_data == data);
524 }
525
526 gboolean
527 g_source_remove_by_source_data (gpointer source_data)
528 {
529   GHook *hook;
530
531   G_LOCK (main_loop);
532
533   hook = g_hook_find (&source_list, TRUE, 
534                       g_source_find_source_data, source_data);
535   if (hook)
536     g_hook_destroy_link (&source_list, hook);
537
538   G_UNLOCK (main_loop);
539
540   return hook != NULL;
541 }
542
543 static gboolean
544 g_source_find_funcs_user_data (GHook   *hook,
545                                gpointer data)
546 {
547   gpointer *d = data;
548
549   return hook->func == d[0] && hook->data == d[1];
550 }
551
552 gboolean
553 g_source_remove_by_funcs_user_data (GSourceFuncs *funcs,
554                                     gpointer      user_data)
555 {
556   gpointer d[2];
557   GHook *hook;
558
559   g_return_val_if_fail (funcs != NULL, FALSE);
560
561   G_LOCK (main_loop);
562
563   d[0] = funcs;
564   d[1] = user_data;
565
566   hook = g_hook_find (&source_list, TRUE,
567                       g_source_find_funcs_user_data, d);
568   if (hook)
569     g_hook_destroy_link (&source_list, hook);
570
571   G_UNLOCK (main_loop);
572
573   return hook != NULL;
574 }
575
576 void
577 g_get_current_time (GTimeVal *result)
578 {
579 #ifndef _MSC_VER
580   struct timeval r;
581   g_return_if_fail (result != NULL);
582
583   /*this is required on alpha, there the timeval structs are int's
584     not longs and a cast only would fail horribly*/
585   gettimeofday (&r, NULL);
586   result->tv_sec = r.tv_sec;
587   result->tv_usec = r.tv_usec;
588 #else
589   /* Avoid calling time() except for the first time.
590    * GetTickCount() should be pretty fast and low-level?
591    * I could also use ftime() but it seems unnecessarily overheady.
592    */
593   static DWORD start_tick = 0;
594   static time_t start_time;
595   DWORD tick;
596   time_t t;
597
598   g_return_if_fail (result != NULL);
599  
600   if (start_tick == 0)
601     {
602       start_tick = GetTickCount ();
603       time (&start_time);
604     }
605
606   tick = GetTickCount ();
607
608   result->tv_sec = (tick - start_tick) / 1000 + start_time;
609   result->tv_usec = ((tick - start_tick) % 1000) * 1000;
610 #endif
611 }
612
613 /* Running the main loop */
614
615 /* HOLDS: main_loop_lock */
616 static void
617 g_main_dispatch (GTimeVal *current_time)
618 {
619   while (pending_dispatches != NULL)
620     {
621       gboolean need_destroy;
622       GSource *source = pending_dispatches->data;
623       GSList *tmp_list;
624
625       tmp_list = pending_dispatches;
626       pending_dispatches = g_slist_remove_link (pending_dispatches, pending_dispatches);
627       g_slist_free_1 (tmp_list);
628
629       if (G_HOOK_IS_VALID (source))
630         {
631           gboolean was_in_call;
632           gpointer hook_data = source->hook.data;
633           gpointer source_data = source->source_data;
634           gboolean (*dispatch) (gpointer,
635                                 GTimeVal *,
636                                 gpointer);
637
638           dispatch = ((GSourceFuncs *) source->hook.func)->dispatch;
639           
640           was_in_call = G_HOOK_IN_CALL (source);
641           source->hook.flags |= G_HOOK_FLAG_IN_CALL;
642
643           G_UNLOCK (main_loop);
644           need_destroy = ! dispatch (source_data,
645                                      current_time,
646                                      hook_data);
647           G_LOCK (main_loop);
648
649           if (!was_in_call)
650             source->hook.flags &= ~G_HOOK_FLAG_IN_CALL;
651           
652           if (need_destroy && G_HOOK_IS_VALID (source))
653             g_hook_destroy_link (&source_list, (GHook *) source);
654         }
655
656       g_hook_unref (&source_list, (GHook*) source);
657     }
658 }
659
660 /* g_main_iterate () runs a single iteration of the mainloop, or,
661  * if !dispatch checks to see if any sources need dispatching.
662  * basic algorithm for dispatch=TRUE:
663  *
664  * 1) while the list of currently pending sources is non-empty,
665  *    we call (*dispatch) on those that are !IN_CALL or can_recurse,
666  *    removing sources from the list after each returns.
667  *    the return value of (*dispatch) determines whether the source
668  *    itself is kept alive.
669  *
670  * 2) call (*prepare) for sources that are not yet SOURCE_READY and
671  *    are !IN_CALL or can_recurse. a return value of TRUE determines
672  *    that the source would like to be dispatched immediatedly, it
673  *    is then flagged as SOURCE_READY.
674  *
675  * 3) poll with the pollfds from all sources at the priority of the
676  *    first source flagged as SOURCE_READY. if there are any sources
677  *    flagged as SOURCE_READY, we use a timeout of 0 or the minimum
678  *    of all timouts otherwise.
679  *
680  * 4) for each source !IN_CALL or can_recurse, if SOURCE_READY or
681  *    (*check) returns true, add the source to the pending list.
682  *    once one source returns true, stop after checking all sources
683  *    at that priority.
684  *
685  * 5) while the list of currently pending sources is non-empty,
686  *    call (*dispatch) on each source, removing the source
687  *    after the call.
688  *
689  */
690 static gboolean
691 g_main_iterate (gboolean block,
692                 gboolean dispatch)
693 {
694   GHook *hook;
695   GTimeVal current_time  ={ 0, 0 };
696   gint n_ready = 0;
697   gint current_priority = 0;
698   gint timeout;
699   gboolean retval = FALSE;
700
701   g_return_val_if_fail (!block || dispatch, FALSE);
702
703   g_get_current_time (&current_time);
704
705   G_LOCK (main_loop);
706   
707   /* If recursing, finish up current dispatch, before starting over */
708   if (pending_dispatches)
709     {
710       if (dispatch)
711         g_main_dispatch (&current_time);
712       
713       G_UNLOCK (main_loop);
714
715       return TRUE;
716     }
717
718   /* Prepare all sources */
719
720   timeout = block ? -1 : 0;
721   
722   hook = g_hook_first_valid (&source_list, TRUE);
723   while (hook)
724     {
725       GSource *source = (GSource *)hook;
726       gint source_timeout = -1;
727
728       if ((n_ready > 0) && (source->priority > current_priority))
729         {
730           g_hook_unref (&source_list, hook);
731           break;
732         }
733       if (G_HOOK_IN_CALL (hook) && !(hook->flags & G_SOURCE_CAN_RECURSE))
734         {
735           hook = g_hook_next_valid (&source_list, hook, TRUE);
736           continue;
737         }
738
739       if (!(hook->flags & G_SOURCE_READY))
740         {
741           gboolean (*prepare)  (gpointer  source_data, 
742                                 GTimeVal *current_time,
743                                 gint     *timeout);
744
745           prepare = ((GSourceFuncs *) hook->func)->prepare;
746           in_check_or_prepare++;
747           G_UNLOCK (main_loop);
748
749           if ((*prepare) (source->source_data, &current_time, &source_timeout))
750             hook->flags |= G_SOURCE_READY;
751           
752           G_LOCK (main_loop);
753           in_check_or_prepare--;
754         }
755
756       if (hook->flags & G_SOURCE_READY)
757         {
758           if (!dispatch)
759             {
760               g_hook_unref (&source_list, hook);
761               G_UNLOCK (main_loop);
762
763               return TRUE;
764             }
765           else
766             {
767               n_ready++;
768               current_priority = source->priority;
769               timeout = 0;
770             }
771         }
772       
773       if (source_timeout >= 0)
774         {
775           if (timeout < 0)
776             timeout = source_timeout;
777           else
778             timeout = MIN (timeout, source_timeout);
779         }
780
781       hook = g_hook_next_valid (&source_list, hook, TRUE);
782     }
783
784   /* poll(), if necessary */
785
786   g_main_poll (timeout, n_ready > 0, current_priority);
787
788   /* Check to see what sources need to be dispatched */
789
790   n_ready = 0;
791   
792   hook = g_hook_first_valid (&source_list, TRUE);
793   while (hook)
794     {
795       GSource *source = (GSource *)hook;
796
797       if ((n_ready > 0) && (source->priority > current_priority))
798         {
799           g_hook_unref (&source_list, hook);
800           break;
801         }
802       if (G_HOOK_IN_CALL (hook) && !(hook->flags & G_SOURCE_CAN_RECURSE))
803         {
804           hook = g_hook_next_valid (&source_list, hook, TRUE);
805           continue;
806         }
807
808       if (!(hook->flags & G_SOURCE_READY))
809         {
810           gboolean (*check) (gpointer  source_data,
811                              GTimeVal *current_time);
812
813           check = ((GSourceFuncs *) hook->func)->check;
814           in_check_or_prepare++;
815           G_UNLOCK (main_loop);
816           
817           if ((*check) (source->source_data, &current_time))
818             hook->flags |= G_SOURCE_READY;
819
820           G_LOCK (main_loop);
821           in_check_or_prepare--;
822         }
823
824       if (hook->flags & G_SOURCE_READY)
825         {
826           if (dispatch)
827             {
828               hook->flags &= ~G_SOURCE_READY;
829               g_hook_ref (&source_list, hook);
830               pending_dispatches = g_slist_prepend (pending_dispatches, source);
831               current_priority = source->priority;
832               n_ready++;
833             }
834           else
835             {
836               g_hook_unref (&source_list, hook);
837               G_UNLOCK (main_loop);
838
839               return TRUE;
840             }
841         }
842       
843       hook = g_hook_next_valid (&source_list, hook, TRUE);
844     }
845
846   /* Now invoke the callbacks */
847
848   if (pending_dispatches)
849     {
850       pending_dispatches = g_slist_reverse (pending_dispatches);
851       g_main_dispatch (&current_time);
852       retval = TRUE;
853     }
854
855   G_UNLOCK (main_loop);
856
857   return retval;
858 }
859
860 /* See if any events are pending
861  */
862 gboolean 
863 g_main_pending (void)
864 {
865   return in_check_or_prepare ? FALSE : g_main_iterate (FALSE, FALSE);
866 }
867
868 /* Run a single iteration of the mainloop. If block is FALSE,
869  * will never block
870  */
871 gboolean
872 g_main_iteration (gboolean block)
873 {
874   if (in_check_or_prepare)
875     {
876       g_warning ("g_main_iteration(): called recursively from within a source's check() or "
877                  "prepare() member or from a second thread, iteration not possible");
878       return FALSE;
879     }
880   else
881     return g_main_iterate (block, TRUE);
882 }
883
884 GMainLoop*
885 g_main_new (gboolean is_running)
886 {
887   GMainLoop *loop;
888
889   loop = g_new0 (GMainLoop, 1);
890   loop->is_running = is_running != FALSE;
891
892   return loop;
893 }
894
895 void 
896 g_main_run (GMainLoop *loop)
897 {
898   g_return_if_fail (loop != NULL);
899
900   if (in_check_or_prepare)
901     {
902       g_warning ("g_main_run(): called recursively from within a source's check() or "
903                  "prepare() member or from a second thread, iteration not possible");
904       return;
905     }
906
907   loop->is_running = TRUE;
908   while (loop->is_running)
909     g_main_iterate (TRUE, TRUE);
910 }
911
912 void 
913 g_main_quit (GMainLoop *loop)
914 {
915   g_return_if_fail (loop != NULL);
916
917   loop->is_running = FALSE;
918 }
919
920 void 
921 g_main_destroy (GMainLoop *loop)
922 {
923   g_return_if_fail (loop != NULL);
924
925   g_free (loop);
926 }
927
928 gboolean
929 g_main_is_running (GMainLoop *loop)
930 {
931   g_return_val_if_fail (loop != NULL, FALSE);
932
933   return loop->is_running;
934 }
935
936 /* HOLDS: main_loop_lock */
937 static void
938 g_main_poll (gint     timeout,
939              gboolean use_priority,
940              gint     priority)
941 {
942   GPollFD *fd_array;
943   GPollRec *pollrec;
944
945   gint i;
946   gint npoll;
947 #ifdef G_THREADS_ENABLED
948 #ifndef NATIVE_WIN32
949   if (wake_up_pipe[0] < 0)
950     {
951       if (pipe (wake_up_pipe) < 0)
952         g_error ("Cannot create pipe main loop wake-up: %s\n",
953                  g_strerror (errno));
954
955       wake_up_rec.fd = wake_up_pipe[0];
956       wake_up_rec.events = G_IO_IN;
957       g_main_add_poll_unlocked (0, &wake_up_rec);
958     }
959 #else
960   if (wake_up_semaphore == NULL)
961     {
962       if ((wake_up_semaphore = CreateSemaphore (NULL, 0, 100, NULL)) == NULL)
963         g_error ("Cannot create wake-up semaphore: %d", GetLastError ());
964       wake_up_rec.fd = (gint) wake_up_semaphore;
965       wake_up_rec.events = G_IO_IN;
966       g_main_add_poll_unlocked (0, &wake_up_rec);
967     }
968 #endif
969 #endif
970   fd_array = g_new (GPollFD, n_poll_records);
971  
972   pollrec = poll_records;
973   i = 0;
974   while (pollrec && (!use_priority || priority >= pollrec->priority))
975     {
976       fd_array[i].fd = pollrec->fd->fd;
977       fd_array[i].events = pollrec->fd->events;
978       fd_array[i].revents = 0;
979         
980       pollrec = pollrec->next;
981       i++;
982     }
983 #ifdef G_THREADS_ENABLED
984   poll_waiting = TRUE;
985 #endif
986   G_UNLOCK (main_loop);
987   npoll = i;
988   (*poll_func) (fd_array, npoll, timeout);
989   G_LOCK (main_loop);
990
991 #ifdef G_THREADS_ENABLED
992   if (!poll_waiting)
993     {
994 #ifndef NATIVE_WIN32
995       gchar c;
996       read (wake_up_pipe[0], &c, 1);
997 #endif
998     }
999   else
1000     poll_waiting = FALSE;
1001 #endif
1002
1003   pollrec = poll_records;
1004   i = 0;
1005   while (i < npoll)
1006     {
1007       pollrec->fd->revents = fd_array[i].revents;
1008       pollrec = pollrec->next;
1009       i++;
1010     }
1011
1012   g_free (fd_array);
1013 }
1014
1015 void 
1016 g_main_add_poll (GPollFD *fd,
1017                  gint     priority)
1018 {
1019   G_LOCK (main_loop);
1020   g_main_add_poll_unlocked (priority, fd);
1021   G_UNLOCK (main_loop);
1022 }
1023
1024 /* HOLDS: main_loop_lock */
1025 static void 
1026 g_main_add_poll_unlocked (gint     priority,
1027                           GPollFD *fd)
1028 {
1029   GPollRec *lastrec, *pollrec, *newrec;
1030
1031   if (!poll_chunk)
1032     poll_chunk = g_mem_chunk_create (GPollRec, 32, G_ALLOC_ONLY);
1033
1034   if (poll_free_list)
1035     {
1036       newrec = poll_free_list;
1037       poll_free_list = newrec->next;
1038     }
1039   else
1040     newrec = g_chunk_new (GPollRec, poll_chunk);
1041
1042   newrec->fd = fd;
1043   newrec->priority = priority;
1044
1045   lastrec = NULL;
1046   pollrec = poll_records;
1047   while (pollrec && priority >= pollrec->priority)
1048     {
1049       lastrec = pollrec;
1050       pollrec = pollrec->next;
1051     }
1052   
1053   if (lastrec)
1054     lastrec->next = newrec;
1055   else
1056     poll_records = newrec;
1057
1058   newrec->next = pollrec;
1059
1060   n_poll_records++;
1061 }
1062
1063 void 
1064 g_main_remove_poll (GPollFD *fd)
1065 {
1066   GPollRec *pollrec, *lastrec;
1067
1068   G_LOCK (main_loop);
1069   
1070   lastrec = NULL;
1071   pollrec = poll_records;
1072
1073   while (pollrec)
1074     {
1075       if (pollrec->fd == fd)
1076         {
1077           if (lastrec != NULL)
1078             lastrec->next = pollrec->next;
1079           else
1080             poll_records = pollrec->next;
1081
1082           pollrec->next = poll_free_list;
1083           poll_free_list = pollrec;
1084
1085           n_poll_records--;
1086           break;
1087         }
1088       lastrec = pollrec;
1089       pollrec = pollrec->next;
1090     }
1091
1092   G_UNLOCK (main_loop);
1093 }
1094
1095 void 
1096 g_main_set_poll_func (GPollFunc func)
1097 {
1098   if (func)
1099     poll_func = func;
1100   else
1101 #ifdef HAVE_POLL
1102     poll_func = (GPollFunc) poll;
1103 #else
1104     poll_func = (GPollFunc) g_poll;
1105 #endif
1106 }
1107
1108 /* Timeouts */
1109
1110 static gboolean 
1111 g_timeout_prepare  (gpointer source_data, 
1112                     GTimeVal *current_time,
1113                     gint    *timeout)
1114 {
1115   glong msec;
1116   GTimeoutData *data = source_data;
1117
1118   msec = (data->expiration.tv_sec  - current_time->tv_sec) * 1000 +
1119          (data->expiration.tv_usec - current_time->tv_usec) / 1000;
1120
1121   *timeout = (msec <= 0) ? 0 : msec;
1122
1123   return (msec <= 0);
1124 }
1125
1126 static gboolean 
1127 g_timeout_check    (gpointer source_data,
1128                     GTimeVal *current_time)
1129 {
1130   GTimeoutData *data = source_data;
1131
1132   return (data->expiration.tv_sec < current_time->tv_sec) ||
1133          ((data->expiration.tv_sec == current_time->tv_sec) &&
1134           (data->expiration.tv_usec <= current_time->tv_usec));
1135 }
1136
1137 static gboolean
1138 g_timeout_dispatch (gpointer source_data, 
1139                     GTimeVal *current_time,
1140                     gpointer user_data)
1141 {
1142   GTimeoutData *data = source_data;
1143
1144   if (data->callback (user_data))
1145     {
1146       guint seconds = data->interval / 1000;
1147       guint msecs = data->interval - seconds * 1000;
1148
1149       data->expiration.tv_sec = current_time->tv_sec + seconds;
1150       data->expiration.tv_usec = current_time->tv_usec + msecs * 1000;
1151       if (data->expiration.tv_usec >= 1000000)
1152         {
1153           data->expiration.tv_usec -= 1000000;
1154           data->expiration.tv_sec++;
1155         }
1156       return TRUE;
1157     }
1158   else
1159     return FALSE;
1160 }
1161
1162 guint 
1163 g_timeout_add_full (gint           priority,
1164                     guint          interval, 
1165                     GSourceFunc    function,
1166                     gpointer       data,
1167                     GDestroyNotify notify)
1168 {
1169   guint seconds;
1170   guint msecs;
1171   GTimeoutData *timeout_data = g_new (GTimeoutData, 1);
1172
1173   timeout_data->interval = interval;
1174   timeout_data->callback = function;
1175   g_get_current_time (&timeout_data->expiration);
1176
1177   seconds = timeout_data->interval / 1000;
1178   msecs = timeout_data->interval - seconds * 1000;
1179
1180   timeout_data->expiration.tv_sec += seconds;
1181   timeout_data->expiration.tv_usec += msecs * 1000;
1182   if (timeout_data->expiration.tv_usec >= 1000000)
1183     {
1184       timeout_data->expiration.tv_usec -= 1000000;
1185       timeout_data->expiration.tv_sec++;
1186     }
1187
1188   return g_source_add (priority, FALSE, &timeout_funcs, timeout_data, data, notify);
1189 }
1190
1191 guint 
1192 g_timeout_add (guint32        interval,
1193                GSourceFunc    function,
1194                gpointer       data)
1195 {
1196   return g_timeout_add_full (G_PRIORITY_DEFAULT, 
1197                              interval, function, data, NULL);
1198 }
1199
1200 /* Idle functions */
1201
1202 static gboolean 
1203 g_idle_prepare  (gpointer source_data, 
1204                  GTimeVal *current_time,
1205                  gint     *timeout)
1206 {
1207   timeout = 0;
1208   return TRUE;
1209 }
1210
1211 static gboolean 
1212 g_idle_check    (gpointer  source_data,
1213                  GTimeVal *current_time)
1214 {
1215   return TRUE;
1216 }
1217
1218 static gboolean
1219 g_idle_dispatch (gpointer source_data, 
1220                  GTimeVal *current_time,
1221                  gpointer user_data)
1222 {
1223   GSourceFunc func = source_data;
1224
1225   return func (user_data);
1226 }
1227
1228 guint 
1229 g_idle_add_full (gint           priority,
1230                  GSourceFunc    function,
1231                  gpointer       data,
1232                  GDestroyNotify notify)
1233 {
1234   g_return_val_if_fail (function != NULL, 0);
1235
1236   return g_source_add (priority, FALSE, &idle_funcs, function, data, notify);
1237 }
1238
1239 guint 
1240 g_idle_add (GSourceFunc    function,
1241             gpointer       data)
1242 {
1243   return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, function, data, NULL);
1244 }
1245
1246 gboolean
1247 g_idle_remove_by_data (gpointer data)
1248 {
1249   return g_source_remove_by_funcs_user_data (&idle_funcs, data);
1250 }