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