1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * gmain.c: Main loop abstraction, timeouts, and idle functions
5 * Copyright 1998 Owen Taylor
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.
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.
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.
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/.
36 /* uncomment the next line to get poll() debugging info */
37 /* #define G_MAIN_POLL_DEBUG */
40 #include <sys/types.h>
42 #ifdef HAVE_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 */
52 #endif /* HAVE_UNISTD_H */
58 #endif /* G_OS_WIN32 */
61 #include <net/socket.h>
62 #endif /* G_OS_BEOS */
66 typedef struct _GTimeoutData GTimeoutData;
67 typedef struct _GSource GSource;
68 typedef struct _GPollRec GPollRec;
72 G_SOURCE_READY = 1 << G_HOOK_FLAG_USER_SHIFT,
73 G_SOURCE_CAN_RECURSE = 1 << (G_HOOK_FLAG_USER_SHIFT + 1)
102 /* Forward declarations */
104 static gint g_source_compare (GHook *a,
106 static void g_source_destroy_func (GHookList *hook_list,
108 static void g_main_poll (gint timeout,
109 gboolean use_priority,
111 static void g_main_add_poll_unlocked (gint priority,
113 static void g_main_wakeup (void);
115 static gboolean g_timeout_prepare (gpointer source_data,
116 GTimeVal *current_time,
119 static gboolean g_timeout_check (gpointer source_data,
120 GTimeVal *current_time,
122 static gboolean g_timeout_dispatch (gpointer source_data,
123 GTimeVal *dispatch_time,
125 static gboolean g_idle_prepare (gpointer source_data,
126 GTimeVal *current_time,
129 static gboolean g_idle_check (gpointer source_data,
130 GTimeVal *current_time,
132 static gboolean g_idle_dispatch (gpointer source_data,
133 GTimeVal *dispatch_time,
138 static GSList *pending_dispatches = NULL;
139 static GHookList source_list = { 0 };
140 static gint in_check_or_prepare = 0;
142 /* The following lock is used for both the list of sources
143 * and the list of poll records
145 G_LOCK_DEFINE_STATIC (main_loop);
147 static GSourceFuncs timeout_funcs =
155 static GSourceFuncs idle_funcs =
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;
168 #ifdef G_THREADS_ENABLED
170 /* this pipe is used to wake up the main loop when a source is added.
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;
179 /* Flag indicating whether the set of fd's changed during a poll */
180 static gboolean poll_changed = FALSE;
181 #endif /* G_THREADS_ENABLED */
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);
188 static GPollFunc poll_func = (GPollFunc) poll;
189 #else /* !HAVE_POLL */
193 g_poll (GPollFD *fds,
197 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
198 gboolean poll_msgs = FALSE;
205 for (f = fds; f < &fds[nfds]; ++f)
208 if (f->events & G_IO_IN)
210 if (f->fd == G_WIN32_MSG_HANDLE)
214 #ifdef G_MAIN_POLL_DEBUG
215 g_print ("g_poll: waiting for %#x\n", f->fd);
217 handles[nhandles++] = (HANDLE) f->fd;
227 /* Waiting for messages, and maybe events */
230 if (timeout == INFINITE)
232 /* Waiting just for messages, infinite timeout
233 * -> Use PeekMessage, then WaitMessage
235 #ifdef G_MAIN_POLL_DEBUG
236 g_print ("PeekMessage, then WaitMessage\n");
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;
244 else if (timeout == 0)
246 /* Waiting just for messages, zero timeout
249 #ifdef G_MAIN_POLL_DEBUG
250 g_print ("PeekMessage\n");
252 if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
253 ready = WAIT_OBJECT_0;
255 ready = WAIT_TIMEOUT;
259 /* Waiting just for messages, some timeout
260 * -> First try PeekMessage, then set a timer, wait for message,
261 * kill timer, use PeekMessage
263 #ifdef G_MAIN_POLL_DEBUG
264 g_print ("PeekMessage\n");
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");
272 #ifdef G_MAIN_POLL_DEBUG
273 g_print ("WaitMessage\n");
276 KillTimer (NULL, timer);
277 if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)
278 && msg.message != WM_TIMER)
279 ready = WAIT_OBJECT_0;
281 ready = WAIT_TIMEOUT;
287 /* Wait for either message or event
288 * -> Use MsgWaitForMultipleObjects
290 #ifdef G_MAIN_POLL_DEBUG
291 g_print ("MsgWaitForMultipleObjects(%d, %d)\n", nhandles, timeout);
293 ready = MsgWaitForMultipleObjects (nhandles, handles, FALSE,
294 timeout, QS_ALLINPUT);
296 if (ready == WAIT_FAILED)
297 g_warning ("g_poll: MsgWaitForMultipleObjects failed");
300 else if (nhandles == 0)
302 /* Wait for nothing (huh?) */
307 /* Wait for just events
308 * -> Use WaitForMultipleObjects
310 #ifdef G_MAIN_POLL_DEBUG
311 g_print ("WaitForMultipleObjects(%d, %d)\n", nhandles, timeout);
313 ready = WaitForMultipleObjects (nhandles, handles, FALSE, timeout);
314 if (ready == WAIT_FAILED)
315 g_warning ("g_poll: WaitForMultipleObjects failed");
318 for (f = fds; f < &fds[nfds]; ++f)
321 if (ready == WAIT_FAILED)
323 else if (ready == WAIT_TIMEOUT)
325 else if (poll_msgs && ready == WAIT_OBJECT_0 + nhandles)
327 for (f = fds; f < &fds[nfds]; ++f)
330 if (f->events & G_IO_IN)
331 if (f->fd == G_WIN32_MSG_HANDLE)
332 f->revents |= G_IO_IN;
335 else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)
336 for (f = fds; f < &fds[nfds]; ++f)
338 if ((f->events & G_IO_IN)
339 && f->fd == (gint) handles[ready - WAIT_OBJECT_0])
341 f->revents |= G_IO_IN;
342 #ifdef G_MAIN_POLL_DEBUG
343 g_print ("g_poll: got event %#x\n", f->fd);
346 ResetEvent ((HANDLE) f->fd);
351 if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)
352 return ready - WAIT_OBJECT_0 + 1;
357 #else /* !G_OS_WIN32 */
359 /* The following implementation of poll() comes from the GNU C Library.
360 * Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
363 #include <string.h> /* for bzero on BSD systems */
365 #ifdef HAVE_SYS_SELECT_H
366 #include <sys/select.h>
367 #endif /* HAVE_SYS_SELECT_H */
371 #endif /* G_OS_BEOS */
374 # define SELECT_MASK fd_set
375 #else /* !NO_FD_SET */
377 typedef long fd_mask;
380 # define SELECT_MASK void
382 # define SELECT_MASK int
383 # endif /* !_IBMR2 */
384 #endif /* !NO_FD_SET */
387 g_poll (GPollFD *fds,
392 SELECT_MASK rset, wset, xset;
401 for (f = fds; f < &fds[nfds]; ++f)
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)))
414 tv.tv_sec = timeout / 1000;
415 tv.tv_usec = (timeout % 1000) * 1000;
417 ready = select (maxfd + 1, &rset, &wset, &xset,
418 timeout == -1 ? NULL : &tv);
420 for (f = fds; f < &fds[nfds]; ++f)
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;
437 #endif /* !G_OS_WIN32 */
439 static GPollFunc poll_func = g_poll;
440 #endif /* !HAVE_POLL */
442 /* Hooks for adding to the main loop */
444 /* Use knowledge of insert_sorted algorithm here to make
445 * sure we insert at the end of equal priority items
448 g_source_compare (GHook *a,
451 GSource *source_a = (GSource *)a;
452 GSource *source_b = (GSource *)b;
454 return (source_a->priority < source_b->priority) ? -1 : 1;
457 /* HOLDS: main_loop lock */
459 g_source_destroy_func (GHookList *hook_list,
462 GSource *source = (GSource*) hook;
463 GDestroyNotify destroy;
465 G_UNLOCK (main_loop);
467 destroy = hook->destroy;
469 destroy (hook->data);
471 destroy = ((GSourceFuncs*) hook->func)->destroy;
473 destroy (source->source_data);
479 g_source_add (gint priority,
480 gboolean can_recurse,
482 gpointer source_data,
484 GDestroyNotify notify)
491 if (!source_list.is_setup)
493 g_hook_list_init (&source_list, sizeof (GSource));
495 source_list.hook_destroy = G_HOOK_DEFERRED_DESTROY;
496 source_list.hook_free = g_source_destroy_func;
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;
506 g_hook_insert_sorted (&source_list,
511 source->hook.flags |= G_SOURCE_CAN_RECURSE;
513 return_val = source->hook.hook_id;
515 #ifdef G_THREADS_ENABLED
516 /* Now wake up the main loop if it is waiting in the poll() */
520 G_UNLOCK (main_loop);
526 g_source_remove (guint tag)
530 g_return_val_if_fail (tag > 0, FALSE);
534 hook = g_hook_get (&source_list, tag);
536 g_hook_destroy_link (&source_list, hook);
538 G_UNLOCK (main_loop);
544 g_source_remove_by_user_data (gpointer user_data)
550 hook = g_hook_find_data (&source_list, TRUE, user_data);
552 g_hook_destroy_link (&source_list, hook);
554 G_UNLOCK (main_loop);
560 g_source_find_source_data (GHook *hook,
563 GSource *source = (GSource *)hook;
565 return (source->source_data == data);
569 g_source_remove_by_source_data (gpointer source_data)
575 hook = g_hook_find (&source_list, TRUE,
576 g_source_find_source_data, source_data);
578 g_hook_destroy_link (&source_list, hook);
580 G_UNLOCK (main_loop);
586 g_source_find_funcs_user_data (GHook *hook,
591 return hook->func == d[0] && hook->data == d[1];
595 g_source_remove_by_funcs_user_data (GSourceFuncs *funcs,
601 g_return_val_if_fail (funcs != NULL, FALSE);
608 hook = g_hook_find (&source_list, TRUE,
609 g_source_find_funcs_user_data, d);
611 g_hook_destroy_link (&source_list, hook);
613 G_UNLOCK (main_loop);
619 g_get_current_time (GTimeVal *result)
624 g_return_if_fail (result != NULL);
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;
635 g_return_if_fail (result != NULL);
637 GetSystemTimeAsFileTime (&filetime);
638 t = ((gint64) filetime.dwLowDateTime) +
639 ((gint64) filetime.dwHighDateTime) * G_GINT64_CONSTANT (0x100000000);
641 result->tv_sec = (t - G_GINT64_CONSTANT (0x19db1ded53e8000)) / 10000000;
642 result->tv_usec = (t % 10000000) / 10;
646 /* Running the main loop */
648 /* HOLDS: main_loop_lock */
650 g_main_dispatch (GTimeVal *dispatch_time)
652 while (pending_dispatches != NULL)
654 gboolean need_destroy;
655 GSource *source = pending_dispatches->data;
658 tmp_list = pending_dispatches;
659 pending_dispatches = g_slist_remove_link (pending_dispatches, pending_dispatches);
660 g_slist_free_1 (tmp_list);
662 if (G_HOOK_IS_VALID (source))
664 gboolean was_in_call;
665 gpointer hook_data = source->hook.data;
666 gpointer source_data = source->source_data;
667 gboolean (*dispatch) (gpointer,
671 dispatch = ((GSourceFuncs *) source->hook.func)->dispatch;
673 was_in_call = G_HOOK_IN_CALL (source);
674 source->hook.flags |= G_HOOK_FLAG_IN_CALL;
676 G_UNLOCK (main_loop);
677 need_destroy = ! dispatch (source_data,
683 source->hook.flags &= ~G_HOOK_FLAG_IN_CALL;
685 if (need_destroy && G_HOOK_IS_VALID (source))
686 g_hook_destroy_link (&source_list, (GHook *) source);
689 g_hook_unref (&source_list, (GHook*) source);
693 /* g_main_iterate () runs a single iteration of the mainloop, or,
694 * if !dispatch checks to see if any sources need dispatching.
695 * basic algorithm for dispatch=TRUE:
697 * 1) while the list of currently pending sources is non-empty,
698 * we call (*dispatch) on those that are !IN_CALL or can_recurse,
699 * removing sources from the list after each returns.
700 * the return value of (*dispatch) determines whether the source
701 * itself is kept alive.
703 * 2) call (*prepare) for sources that are not yet SOURCE_READY and
704 * are !IN_CALL or can_recurse. a return value of TRUE determines
705 * that the source would like to be dispatched immediatedly, it
706 * is then flagged as SOURCE_READY.
708 * 3) poll with the pollfds from all sources at the priority of the
709 * first source flagged as SOURCE_READY. if there are any sources
710 * flagged as SOURCE_READY, we use a timeout of 0 or the minimum
711 * of all timouts otherwise.
713 * 4) for each source !IN_CALL or can_recurse, if SOURCE_READY or
714 * (*check) returns true, add the source to the pending list.
715 * once one source returns true, stop after checking all sources
718 * 5) while the list of currently pending sources is non-empty,
719 * call (*dispatch) on each source, removing the source
724 g_main_iterate (gboolean block,
728 GTimeVal current_time = { 0, 0 };
730 gint current_priority = 0;
732 gboolean retval = FALSE;
734 g_return_val_if_fail (!block || dispatch, FALSE);
736 g_get_current_time (¤t_time);
740 #ifdef G_THREADS_ENABLED
743 g_warning("g_main_iterate(): main loop already active in another thread");
744 G_UNLOCK (main_loop);
747 #endif G_THREADS_ENABLED
749 /* If recursing, finish up current dispatch, before starting over */
750 if (pending_dispatches)
753 g_main_dispatch (¤t_time);
755 G_UNLOCK (main_loop);
760 /* Prepare all sources */
762 timeout = block ? -1 : 0;
764 hook = g_hook_first_valid (&source_list, TRUE);
767 GSource *source = (GSource*) hook;
768 gint source_timeout = -1;
770 if ((n_ready > 0) && (source->priority > current_priority))
772 g_hook_unref (&source_list, hook);
775 if (G_HOOK_IN_CALL (hook) && !(hook->flags & G_SOURCE_CAN_RECURSE))
777 hook = g_hook_next_valid (&source_list, hook, TRUE);
781 if (!(hook->flags & G_SOURCE_READY))
783 gboolean (*prepare) (gpointer source_data,
784 GTimeVal *current_time,
788 prepare = ((GSourceFuncs *) hook->func)->prepare;
789 in_check_or_prepare++;
790 G_UNLOCK (main_loop);
792 if ((*prepare) (source->source_data, ¤t_time, &source_timeout, source->hook.data))
793 hook->flags |= G_SOURCE_READY;
796 in_check_or_prepare--;
799 if (hook->flags & G_SOURCE_READY)
803 g_hook_unref (&source_list, hook);
804 G_UNLOCK (main_loop);
811 current_priority = source->priority;
816 if (source_timeout >= 0)
819 timeout = source_timeout;
821 timeout = MIN (timeout, source_timeout);
824 hook = g_hook_next_valid (&source_list, hook, TRUE);
827 /* poll(), if necessary */
829 g_main_poll (timeout, n_ready > 0, current_priority);
832 g_get_current_time (¤t_time);
834 /* Check to see what sources need to be dispatched */
838 hook = g_hook_first_valid (&source_list, TRUE);
841 GSource *source = (GSource *)hook;
843 if ((n_ready > 0) && (source->priority > current_priority))
845 g_hook_unref (&source_list, hook);
848 if (G_HOOK_IN_CALL (hook) && !(hook->flags & G_SOURCE_CAN_RECURSE))
850 hook = g_hook_next_valid (&source_list, hook, TRUE);
854 if (!(hook->flags & G_SOURCE_READY))
856 gboolean (*check) (gpointer source_data,
857 GTimeVal *current_time,
860 check = ((GSourceFuncs *) hook->func)->check;
861 in_check_or_prepare++;
862 G_UNLOCK (main_loop);
864 if ((*check) (source->source_data, ¤t_time, source->hook.data))
865 hook->flags |= G_SOURCE_READY;
868 in_check_or_prepare--;
871 if (hook->flags & G_SOURCE_READY)
875 hook->flags &= ~G_SOURCE_READY;
876 g_hook_ref (&source_list, hook);
877 pending_dispatches = g_slist_prepend (pending_dispatches, source);
878 current_priority = source->priority;
883 g_hook_unref (&source_list, hook);
884 G_UNLOCK (main_loop);
890 hook = g_hook_next_valid (&source_list, hook, TRUE);
893 /* Now invoke the callbacks */
895 if (pending_dispatches)
897 pending_dispatches = g_slist_reverse (pending_dispatches);
898 g_main_dispatch (¤t_time);
902 G_UNLOCK (main_loop);
907 /* See if any events are pending
910 g_main_pending (void)
912 return in_check_or_prepare ? FALSE : g_main_iterate (FALSE, FALSE);
915 /* Run a single iteration of the mainloop. If block is FALSE,
919 g_main_iteration (gboolean block)
921 if (in_check_or_prepare)
923 g_warning ("g_main_iteration(): called recursively from within a source's check() or "
924 "prepare() member or from a second thread, iteration not possible");
928 return g_main_iterate (block, TRUE);
932 g_main_new (gboolean is_running)
936 loop = g_new0 (GMainLoop, 1);
937 loop->is_running = is_running != FALSE;
943 g_main_run (GMainLoop *loop)
945 g_return_if_fail (loop != NULL);
947 if (in_check_or_prepare)
949 g_warning ("g_main_run(): called recursively from within a source's check() or "
950 "prepare() member or from a second thread, iteration not possible");
954 loop->is_running = TRUE;
955 while (loop->is_running)
956 g_main_iterate (TRUE, TRUE);
960 g_main_quit (GMainLoop *loop)
962 g_return_if_fail (loop != NULL);
964 loop->is_running = FALSE;
968 g_main_destroy (GMainLoop *loop)
970 g_return_if_fail (loop != NULL);
976 g_main_is_running (GMainLoop *loop)
978 g_return_val_if_fail (loop != NULL, FALSE);
980 return loop->is_running;
983 /* HOLDS: main_loop_lock */
985 g_main_poll (gint timeout,
986 gboolean use_priority,
989 #ifdef G_MAIN_POLL_DEBUG
997 #ifdef G_THREADS_ENABLED
999 if (wake_up_pipe[0] < 0)
1001 if (pipe (wake_up_pipe) < 0)
1002 g_error ("Cannot create pipe main loop wake-up: %s\n",
1003 g_strerror (errno));
1005 wake_up_rec.fd = wake_up_pipe[0];
1006 wake_up_rec.events = G_IO_IN;
1007 g_main_add_poll_unlocked (0, &wake_up_rec);
1010 if (wake_up_semaphore == NULL)
1012 if ((wake_up_semaphore = CreateSemaphore (NULL, 0, 100, NULL)) == NULL)
1013 g_error ("Cannot create wake-up semaphore: %s", g_win32_error_message (GetLastError ()));
1014 wake_up_rec.fd = (gint) wake_up_semaphore;
1015 wake_up_rec.events = G_IO_IN;
1016 #ifdef G_MAIN_POLL_DEBUG
1017 g_print ("wake-up semaphore: %#x\n", (guint) wake_up_semaphore);
1019 g_main_add_poll_unlocked (0, &wake_up_rec);
1023 fd_array = g_new (GPollFD, n_poll_records);
1025 pollrec = poll_records;
1027 while (pollrec && (!use_priority || priority >= pollrec->priority))
1029 if (pollrec->fd->events)
1031 fd_array[i].fd = pollrec->fd->fd;
1032 /* In direct contradiction to the Unix98 spec, IRIX runs into
1033 * difficulty if you pass in POLLERR, POLLHUP or POLLNVAL
1034 * flags in the events field of the pollfd while it should
1035 * just ignoring them. So we mask them out here.
1037 fd_array[i].events = pollrec->fd->events & ~(G_IO_ERR|G_IO_HUP|G_IO_NVAL);
1038 fd_array[i].revents = 0;
1042 pollrec = pollrec->next;
1044 #ifdef G_THREADS_ENABLED
1045 poll_waiting = TRUE;
1046 poll_changed = FALSE;
1050 if (npoll || timeout != 0)
1052 #ifdef G_MAIN_POLL_DEBUG
1053 g_print ("g_main_poll(%d) timeout: %d\n", npoll, timeout);
1054 poll_timer = g_timer_new ();
1057 G_UNLOCK (main_loop);
1058 if ((*poll_func) (fd_array, npoll, timeout) < 0)
1059 g_warning ("poll(2) failed due to: %s.",
1060 g_strerror (errno));
1063 #ifdef G_MAIN_POLL_DEBUG
1064 g_print ("g_main_poll(%d) timeout: %d - elapsed %12.10f seconds",
1067 g_timer_elapsed (poll_timer, NULL));
1068 g_timer_destroy (poll_timer);
1069 pollrec = poll_records;
1073 if (pollrec->fd->events)
1075 if (fd_array[i].revents)
1077 g_print (" [%d:", fd_array[i].fd);
1078 if (fd_array[i].revents & G_IO_IN)
1080 if (fd_array[i].revents & G_IO_OUT)
1082 if (fd_array[i].revents & G_IO_PRI)
1084 if (fd_array[i].revents & G_IO_ERR)
1086 if (fd_array[i].revents & G_IO_HUP)
1088 if (fd_array[i].revents & G_IO_NVAL)
1094 pollrec = pollrec->next;
1098 } /* if (npoll || timeout != 0) */
1100 #ifdef G_THREADS_ENABLED
1105 read (wake_up_pipe[0], &c, 1);
1109 poll_waiting = FALSE;
1111 /* If the set of poll file descriptors changed, bail out
1112 * and let the main loop rerun
1121 pollrec = poll_records;
1125 if (pollrec->fd->events)
1127 pollrec->fd->revents = fd_array[i].revents;
1130 pollrec = pollrec->next;
1137 g_main_add_poll (GPollFD *fd,
1141 g_main_add_poll_unlocked (priority, fd);
1142 G_UNLOCK (main_loop);
1145 /* HOLDS: main_loop_lock */
1147 g_main_add_poll_unlocked (gint priority,
1150 GPollRec *lastrec, *pollrec, *newrec;
1153 poll_chunk = g_mem_chunk_create (GPollRec, 32, G_ALLOC_ONLY);
1157 newrec = poll_free_list;
1158 poll_free_list = newrec->next;
1161 newrec = g_chunk_new (GPollRec, poll_chunk);
1164 newrec->priority = priority;
1167 pollrec = poll_records;
1168 while (pollrec && priority >= pollrec->priority)
1171 pollrec = pollrec->next;
1175 lastrec->next = newrec;
1177 poll_records = newrec;
1179 newrec->next = pollrec;
1183 #ifdef G_THREADS_ENABLED
1184 poll_changed = TRUE;
1186 /* Now wake up the main loop if it is waiting in the poll() */
1192 g_main_remove_poll (GPollFD *fd)
1194 GPollRec *pollrec, *lastrec;
1199 pollrec = poll_records;
1203 if (pollrec->fd == fd)
1205 if (lastrec != NULL)
1206 lastrec->next = pollrec->next;
1208 poll_records = pollrec->next;
1210 #ifdef ENABLE_GC_FRIENDLY
1212 #endif /* ENABLE_GC_FRIENDLY */
1214 pollrec->next = poll_free_list;
1215 poll_free_list = pollrec;
1221 pollrec = pollrec->next;
1224 #ifdef G_THREADS_ENABLED
1225 poll_changed = TRUE;
1227 /* Now wake up the main loop if it is waiting in the poll() */
1231 G_UNLOCK (main_loop);
1235 g_main_set_poll_func (GPollFunc func)
1241 poll_func = (GPollFunc) poll;
1243 poll_func = (GPollFunc) g_poll;
1249 /* Useful on other platforms, too? */
1252 g_main_win32_get_poll_func (void)
1259 /* Wake the main loop up from a poll() */
1261 g_main_wakeup (void)
1263 #ifdef G_THREADS_ENABLED
1266 poll_waiting = FALSE;
1268 write (wake_up_pipe[1], "A", 1);
1270 ReleaseSemaphore (wake_up_semaphore, 1, NULL);
1279 g_timeout_set_expiration (GTimeoutData *data,
1280 GTimeVal *current_time)
1282 guint seconds = data->interval / 1000;
1283 guint msecs = data->interval - seconds * 1000;
1285 data->expiration.tv_sec = current_time->tv_sec + seconds;
1286 data->expiration.tv_usec = current_time->tv_usec + msecs * 1000;
1287 if (data->expiration.tv_usec >= 1000000)
1289 data->expiration.tv_usec -= 1000000;
1290 data->expiration.tv_sec++;
1295 g_timeout_prepare (gpointer source_data,
1296 GTimeVal *current_time,
1301 GTimeoutData *data = source_data;
1303 msec = ((data->expiration.tv_sec - current_time->tv_sec) * 1000 +
1304 (data->expiration.tv_usec - current_time->tv_usec) / 1000);
1308 else if (msec > data->interval)
1310 /* The system time has been set backwards, so we
1311 * reset the expiration time to now + data->interval;
1312 * this at least avoids hanging for long periods of time.
1314 g_timeout_set_expiration (data, current_time);
1315 msec = data->interval;
1324 g_timeout_check (gpointer source_data,
1325 GTimeVal *current_time,
1328 GTimeoutData *data = source_data;
1330 return ((data->expiration.tv_sec < current_time->tv_sec) ||
1331 ((data->expiration.tv_sec == current_time->tv_sec) &&
1332 (data->expiration.tv_usec <= current_time->tv_usec)));
1336 g_timeout_dispatch (gpointer source_data,
1337 GTimeVal *dispatch_time,
1340 GTimeoutData *data = source_data;
1342 if (data->callback (user_data))
1344 g_timeout_set_expiration (data, dispatch_time);
1353 g_timeout_add_full (gint priority,
1355 GSourceFunc function,
1357 GDestroyNotify notify)
1359 GTimeoutData *timeout_data = g_new (GTimeoutData, 1);
1360 GTimeVal current_time;
1362 timeout_data->interval = interval;
1363 timeout_data->callback = function;
1364 g_get_current_time (¤t_time);
1366 g_timeout_set_expiration (timeout_data, ¤t_time);
1368 return g_source_add (priority, FALSE, &timeout_funcs, timeout_data, data, notify);
1372 g_timeout_add (guint32 interval,
1373 GSourceFunc function,
1376 return g_timeout_add_full (G_PRIORITY_DEFAULT,
1377 interval, function, data, NULL);
1380 /* Idle functions */
1383 g_idle_prepare (gpointer source_data,
1384 GTimeVal *current_time,
1394 g_idle_check (gpointer source_data,
1395 GTimeVal *current_time,
1402 g_idle_dispatch (gpointer source_data,
1403 GTimeVal *dispatch_time,
1406 GSourceFunc func = source_data;
1408 return func (user_data);
1412 g_idle_add_full (gint priority,
1413 GSourceFunc function,
1415 GDestroyNotify notify)
1417 g_return_val_if_fail (function != NULL, 0);
1419 return g_source_add (priority, FALSE, &idle_funcs, function, data, notify);
1423 g_idle_add (GSourceFunc function,
1426 return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, function, data, NULL);
1430 g_idle_remove_by_data (gpointer data)
1432 return g_source_remove_by_funcs_user_data (&idle_funcs, data);