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