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;
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.
636 static DWORD start_tick = 0;
637 static time_t start_time;
640 g_return_if_fail (result != NULL);
644 start_tick = GetTickCount ();
648 tick = GetTickCount ();
650 result->tv_sec = (tick - start_tick) / 1000 + start_time;
651 result->tv_usec = ((tick - start_tick) % 1000) * 1000;
655 /* Running the main loop */
657 /* HOLDS: main_loop_lock */
659 g_main_dispatch (GTimeVal *dispatch_time)
661 while (pending_dispatches != NULL)
663 gboolean need_destroy;
664 GSource *source = pending_dispatches->data;
667 tmp_list = pending_dispatches;
668 pending_dispatches = g_slist_remove_link (pending_dispatches, pending_dispatches);
669 g_slist_free_1 (tmp_list);
671 if (G_HOOK_IS_VALID (source))
673 gboolean was_in_call;
674 gpointer hook_data = source->hook.data;
675 gpointer source_data = source->source_data;
676 gboolean (*dispatch) (gpointer,
680 dispatch = ((GSourceFuncs *) source->hook.func)->dispatch;
682 was_in_call = G_HOOK_IN_CALL (source);
683 source->hook.flags |= G_HOOK_FLAG_IN_CALL;
685 G_UNLOCK (main_loop);
686 need_destroy = ! dispatch (source_data,
692 source->hook.flags &= ~G_HOOK_FLAG_IN_CALL;
694 if (need_destroy && G_HOOK_IS_VALID (source))
695 g_hook_destroy_link (&source_list, (GHook *) source);
698 g_hook_unref (&source_list, (GHook*) source);
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:
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.
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.
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.
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
727 * 5) while the list of currently pending sources is non-empty,
728 * call (*dispatch) on each source, removing the source
733 g_main_iterate (gboolean block,
737 GTimeVal current_time = { 0, 0 };
739 gint current_priority = 0;
741 gboolean retval = FALSE;
743 g_return_val_if_fail (!block || dispatch, FALSE);
745 g_get_current_time (¤t_time);
749 #ifdef G_THREADS_ENABLED
752 g_warning("g_main_iterate(): main loop already active in another thread");
753 G_UNLOCK (main_loop);
756 #endif G_THREADS_ENABLED
758 /* If recursing, finish up current dispatch, before starting over */
759 if (pending_dispatches)
762 g_main_dispatch (¤t_time);
764 G_UNLOCK (main_loop);
769 /* Prepare all sources */
771 timeout = block ? -1 : 0;
773 hook = g_hook_first_valid (&source_list, TRUE);
776 GSource *source = (GSource*) hook;
777 gint source_timeout = -1;
779 if ((n_ready > 0) && (source->priority > current_priority))
781 g_hook_unref (&source_list, hook);
784 if (G_HOOK_IN_CALL (hook) && !(hook->flags & G_SOURCE_CAN_RECURSE))
786 hook = g_hook_next_valid (&source_list, hook, TRUE);
790 if (!(hook->flags & G_SOURCE_READY))
792 gboolean (*prepare) (gpointer source_data,
793 GTimeVal *current_time,
797 prepare = ((GSourceFuncs *) hook->func)->prepare;
798 in_check_or_prepare++;
799 G_UNLOCK (main_loop);
801 if ((*prepare) (source->source_data, ¤t_time, &source_timeout, source->hook.data))
802 hook->flags |= G_SOURCE_READY;
805 in_check_or_prepare--;
808 if (hook->flags & G_SOURCE_READY)
812 g_hook_unref (&source_list, hook);
813 G_UNLOCK (main_loop);
820 current_priority = source->priority;
825 if (source_timeout >= 0)
828 timeout = source_timeout;
830 timeout = MIN (timeout, source_timeout);
833 hook = g_hook_next_valid (&source_list, hook, TRUE);
836 /* poll(), if necessary */
838 g_main_poll (timeout, n_ready > 0, current_priority);
841 g_get_current_time (¤t_time);
843 /* Check to see what sources need to be dispatched */
847 hook = g_hook_first_valid (&source_list, TRUE);
850 GSource *source = (GSource *)hook;
852 if ((n_ready > 0) && (source->priority > current_priority))
854 g_hook_unref (&source_list, hook);
857 if (G_HOOK_IN_CALL (hook) && !(hook->flags & G_SOURCE_CAN_RECURSE))
859 hook = g_hook_next_valid (&source_list, hook, TRUE);
863 if (!(hook->flags & G_SOURCE_READY))
865 gboolean (*check) (gpointer source_data,
866 GTimeVal *current_time,
869 check = ((GSourceFuncs *) hook->func)->check;
870 in_check_or_prepare++;
871 G_UNLOCK (main_loop);
873 if ((*check) (source->source_data, ¤t_time, source->hook.data))
874 hook->flags |= G_SOURCE_READY;
877 in_check_or_prepare--;
880 if (hook->flags & G_SOURCE_READY)
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;
892 g_hook_unref (&source_list, hook);
893 G_UNLOCK (main_loop);
899 hook = g_hook_next_valid (&source_list, hook, TRUE);
902 /* Now invoke the callbacks */
904 if (pending_dispatches)
906 pending_dispatches = g_slist_reverse (pending_dispatches);
907 g_main_dispatch (¤t_time);
911 G_UNLOCK (main_loop);
916 /* See if any events are pending
919 g_main_pending (void)
921 return in_check_or_prepare ? FALSE : g_main_iterate (FALSE, FALSE);
924 /* Run a single iteration of the mainloop. If block is FALSE,
928 g_main_iteration (gboolean block)
930 if (in_check_or_prepare)
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");
937 return g_main_iterate (block, TRUE);
941 g_main_new (gboolean is_running)
945 loop = g_new0 (GMainLoop, 1);
946 loop->is_running = is_running != FALSE;
952 g_main_run (GMainLoop *loop)
954 g_return_if_fail (loop != NULL);
956 if (in_check_or_prepare)
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");
963 loop->is_running = TRUE;
964 while (loop->is_running)
965 g_main_iterate (TRUE, TRUE);
969 g_main_quit (GMainLoop *loop)
971 g_return_if_fail (loop != NULL);
973 loop->is_running = FALSE;
977 g_main_destroy (GMainLoop *loop)
979 g_return_if_fail (loop != NULL);
985 g_main_is_running (GMainLoop *loop)
987 g_return_val_if_fail (loop != NULL, FALSE);
989 return loop->is_running;
992 /* HOLDS: main_loop_lock */
994 g_main_poll (gint timeout,
995 gboolean use_priority,
998 #ifdef G_MAIN_POLL_DEBUG
1006 #ifdef G_THREADS_ENABLED
1008 if (wake_up_pipe[0] < 0)
1010 if (pipe (wake_up_pipe) < 0)
1011 g_error ("Cannot create pipe main loop wake-up: %s\n",
1012 g_strerror (errno));
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);
1019 if (wake_up_semaphore == NULL)
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);
1028 g_main_add_poll_unlocked (0, &wake_up_rec);
1032 fd_array = g_new (GPollFD, n_poll_records);
1034 pollrec = poll_records;
1036 while (pollrec && (!use_priority || priority >= pollrec->priority))
1038 if (pollrec->fd->events)
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.
1046 fd_array[i].events = pollrec->fd->events & ~(G_IO_ERR|G_IO_HUP|G_IO_NVAL);
1047 fd_array[i].revents = 0;
1051 pollrec = pollrec->next;
1053 #ifdef G_THREADS_ENABLED
1054 poll_waiting = TRUE;
1055 poll_changed = FALSE;
1059 if (npoll || timeout != 0)
1061 #ifdef G_MAIN_POLL_DEBUG
1062 g_print ("g_main_poll(%d) timeout: %d\n", npoll, timeout);
1063 poll_timer = g_timer_new ();
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));
1072 #ifdef G_MAIN_POLL_DEBUG
1073 g_print ("g_main_poll(%d) timeout: %d - elapsed %12.10f seconds",
1076 g_timer_elapsed (poll_timer, NULL));
1077 g_timer_destroy (poll_timer);
1078 pollrec = poll_records;
1082 if (pollrec->fd->events)
1084 if (fd_array[i].revents)
1086 g_print (" [%d:", fd_array[i].fd);
1087 if (fd_array[i].revents & G_IO_IN)
1089 if (fd_array[i].revents & G_IO_OUT)
1091 if (fd_array[i].revents & G_IO_PRI)
1093 if (fd_array[i].revents & G_IO_ERR)
1095 if (fd_array[i].revents & G_IO_HUP)
1097 if (fd_array[i].revents & G_IO_NVAL)
1103 pollrec = pollrec->next;
1107 } /* if (npoll || timeout != 0) */
1109 #ifdef G_THREADS_ENABLED
1114 read (wake_up_pipe[0], &c, 1);
1118 poll_waiting = FALSE;
1120 /* If the set of poll file descriptors changed, bail out
1121 * and let the main loop rerun
1130 pollrec = poll_records;
1134 if (pollrec->fd->events)
1136 pollrec->fd->revents = fd_array[i].revents;
1139 pollrec = pollrec->next;
1146 g_main_add_poll (GPollFD *fd,
1150 g_main_add_poll_unlocked (priority, fd);
1151 G_UNLOCK (main_loop);
1154 /* HOLDS: main_loop_lock */
1156 g_main_add_poll_unlocked (gint priority,
1159 GPollRec *lastrec, *pollrec, *newrec;
1162 poll_chunk = g_mem_chunk_create (GPollRec, 32, G_ALLOC_ONLY);
1166 newrec = poll_free_list;
1167 poll_free_list = newrec->next;
1170 newrec = g_chunk_new (GPollRec, poll_chunk);
1173 newrec->priority = priority;
1176 pollrec = poll_records;
1177 while (pollrec && priority >= pollrec->priority)
1180 pollrec = pollrec->next;
1184 lastrec->next = newrec;
1186 poll_records = newrec;
1188 newrec->next = pollrec;
1192 #ifdef G_THREADS_ENABLED
1193 poll_changed = TRUE;
1195 /* Now wake up the main loop if it is waiting in the poll() */
1201 g_main_remove_poll (GPollFD *fd)
1203 GPollRec *pollrec, *lastrec;
1208 pollrec = poll_records;
1212 if (pollrec->fd == fd)
1214 if (lastrec != NULL)
1215 lastrec->next = pollrec->next;
1217 poll_records = pollrec->next;
1219 #ifdef ENABLE_GC_FRIENDLY
1221 #endif /* ENABLE_GC_FRIENDLY */
1223 pollrec->next = poll_free_list;
1224 poll_free_list = pollrec;
1230 pollrec = pollrec->next;
1233 #ifdef G_THREADS_ENABLED
1234 poll_changed = TRUE;
1236 /* Now wake up the main loop if it is waiting in the poll() */
1240 G_UNLOCK (main_loop);
1244 g_main_set_poll_func (GPollFunc func)
1250 poll_func = (GPollFunc) poll;
1252 poll_func = (GPollFunc) g_poll;
1258 /* Useful on other platforms, too? */
1261 g_main_win32_get_poll_func (void)
1268 /* Wake the main loop up from a poll() */
1270 g_main_wakeup (void)
1272 #ifdef G_THREADS_ENABLED
1275 poll_waiting = FALSE;
1277 write (wake_up_pipe[1], "A", 1);
1279 ReleaseSemaphore (wake_up_semaphore, 1, NULL);
1288 g_timeout_set_expiration (GTimeoutData *data,
1289 GTimeVal *current_time)
1291 guint seconds = data->interval / 1000;
1292 guint msecs = data->interval - seconds * 1000;
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)
1298 data->expiration.tv_usec -= 1000000;
1299 data->expiration.tv_sec++;
1304 g_timeout_prepare (gpointer source_data,
1305 GTimeVal *current_time,
1310 GTimeoutData *data = source_data;
1312 msec = ((data->expiration.tv_sec - current_time->tv_sec) * 1000 +
1313 (data->expiration.tv_usec - current_time->tv_usec) / 1000);
1317 else if (msec > data->interval)
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.
1323 g_timeout_set_expiration (data, current_time);
1324 msec = data->interval;
1333 g_timeout_check (gpointer source_data,
1334 GTimeVal *current_time,
1337 GTimeoutData *data = source_data;
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)));
1345 g_timeout_dispatch (gpointer source_data,
1346 GTimeVal *dispatch_time,
1349 GTimeoutData *data = source_data;
1351 if (data->callback (user_data))
1353 g_timeout_set_expiration (data, dispatch_time);
1362 g_timeout_add_full (gint priority,
1364 GSourceFunc function,
1366 GDestroyNotify notify)
1368 GTimeoutData *timeout_data = g_new (GTimeoutData, 1);
1369 GTimeVal current_time;
1371 timeout_data->interval = interval;
1372 timeout_data->callback = function;
1373 g_get_current_time (¤t_time);
1375 g_timeout_set_expiration (timeout_data, ¤t_time);
1377 return g_source_add (priority, FALSE, &timeout_funcs, timeout_data, data, notify);
1381 g_timeout_add (guint32 interval,
1382 GSourceFunc function,
1385 return g_timeout_add_full (G_PRIORITY_DEFAULT,
1386 interval, function, data, NULL);
1389 /* Idle functions */
1392 g_idle_prepare (gpointer source_data,
1393 GTimeVal *current_time,
1403 g_idle_check (gpointer source_data,
1404 GTimeVal *current_time,
1411 g_idle_dispatch (gpointer source_data,
1412 GTimeVal *dispatch_time,
1415 GSourceFunc func = source_data;
1417 return func (user_data);
1421 g_idle_add_full (gint priority,
1422 GSourceFunc function,
1424 GDestroyNotify notify)
1426 g_return_val_if_fail (function != NULL, 0);
1428 return g_source_add (priority, FALSE, &idle_funcs, function, data, notify);
1432 g_idle_add (GSourceFunc function,
1435 return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, function, data, NULL);
1439 g_idle_remove_by_data (gpointer data)
1441 return g_source_remove_by_funcs_user_data (&idle_funcs, data);