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)
622 g_return_if_fail (result != NULL);
624 /*this is required on alpha, there the timeval structs are int's
625 not longs and a cast only would fail horribly*/
626 gettimeofday (&r, NULL);
627 result->tv_sec = r.tv_sec;
628 result->tv_usec = r.tv_usec;
630 /* Avoid calling time() except for the first time.
631 * GetTickCount() should be pretty fast and low-level?
632 * I could also use ftime() but it seems unnecessarily overheady.
634 static DWORD start_tick = 0;
635 static time_t start_time;
638 g_return_if_fail (result != NULL);
642 start_tick = GetTickCount ();
646 tick = GetTickCount ();
648 result->tv_sec = (tick - start_tick) / 1000 + start_time;
649 result->tv_usec = ((tick - start_tick) % 1000) * 1000;
653 /* Running the main loop */
655 /* HOLDS: main_loop_lock */
657 g_main_dispatch (GTimeVal *dispatch_time)
659 while (pending_dispatches != NULL)
661 gboolean need_destroy;
662 GSource *source = pending_dispatches->data;
665 tmp_list = pending_dispatches;
666 pending_dispatches = g_slist_remove_link (pending_dispatches, pending_dispatches);
667 g_slist_free_1 (tmp_list);
669 if (G_HOOK_IS_VALID (source))
671 gboolean was_in_call;
672 gpointer hook_data = source->hook.data;
673 gpointer source_data = source->source_data;
674 gboolean (*dispatch) (gpointer,
678 dispatch = ((GSourceFuncs *) source->hook.func)->dispatch;
680 was_in_call = G_HOOK_IN_CALL (source);
681 source->hook.flags |= G_HOOK_FLAG_IN_CALL;
683 G_UNLOCK (main_loop);
684 need_destroy = ! dispatch (source_data,
690 source->hook.flags &= ~G_HOOK_FLAG_IN_CALL;
692 if (need_destroy && G_HOOK_IS_VALID (source))
693 g_hook_destroy_link (&source_list, (GHook *) source);
696 g_hook_unref (&source_list, (GHook*) source);
700 /* g_main_iterate () runs a single iteration of the mainloop, or,
701 * if !dispatch checks to see if any sources need dispatching.
702 * basic algorithm for dispatch=TRUE:
704 * 1) while the list of currently pending sources is non-empty,
705 * we call (*dispatch) on those that are !IN_CALL or can_recurse,
706 * removing sources from the list after each returns.
707 * the return value of (*dispatch) determines whether the source
708 * itself is kept alive.
710 * 2) call (*prepare) for sources that are not yet SOURCE_READY and
711 * are !IN_CALL or can_recurse. a return value of TRUE determines
712 * that the source would like to be dispatched immediatedly, it
713 * is then flagged as SOURCE_READY.
715 * 3) poll with the pollfds from all sources at the priority of the
716 * first source flagged as SOURCE_READY. if there are any sources
717 * flagged as SOURCE_READY, we use a timeout of 0 or the minimum
718 * of all timouts otherwise.
720 * 4) for each source !IN_CALL or can_recurse, if SOURCE_READY or
721 * (*check) returns true, add the source to the pending list.
722 * once one source returns true, stop after checking all sources
725 * 5) while the list of currently pending sources is non-empty,
726 * call (*dispatch) on each source, removing the source
731 g_main_iterate (gboolean block,
735 GTimeVal current_time = { 0, 0 };
737 gint current_priority = 0;
739 gboolean retval = FALSE;
741 g_return_val_if_fail (!block || dispatch, FALSE);
743 g_get_current_time (¤t_time);
747 #ifdef G_THREADS_ENABLED
750 g_warning("g_main_iterate(): main loop already active in another thread");
751 G_UNLOCK (main_loop);
754 #endif G_THREADS_ENABLED
756 /* If recursing, finish up current dispatch, before starting over */
757 if (pending_dispatches)
760 g_main_dispatch (¤t_time);
762 G_UNLOCK (main_loop);
767 /* Prepare all sources */
769 timeout = block ? -1 : 0;
771 hook = g_hook_first_valid (&source_list, TRUE);
774 GSource *source = (GSource*) hook;
775 gint source_timeout = -1;
777 if ((n_ready > 0) && (source->priority > current_priority))
779 g_hook_unref (&source_list, hook);
782 if (G_HOOK_IN_CALL (hook) && !(hook->flags & G_SOURCE_CAN_RECURSE))
784 hook = g_hook_next_valid (&source_list, hook, TRUE);
788 if (!(hook->flags & G_SOURCE_READY))
790 gboolean (*prepare) (gpointer source_data,
791 GTimeVal *current_time,
795 prepare = ((GSourceFuncs *) hook->func)->prepare;
796 in_check_or_prepare++;
797 G_UNLOCK (main_loop);
799 if ((*prepare) (source->source_data, ¤t_time, &source_timeout, source->hook.data))
800 hook->flags |= G_SOURCE_READY;
803 in_check_or_prepare--;
806 if (hook->flags & G_SOURCE_READY)
810 g_hook_unref (&source_list, hook);
811 G_UNLOCK (main_loop);
818 current_priority = source->priority;
823 if (source_timeout >= 0)
826 timeout = source_timeout;
828 timeout = MIN (timeout, source_timeout);
831 hook = g_hook_next_valid (&source_list, hook, TRUE);
834 /* poll(), if necessary */
836 g_main_poll (timeout, n_ready > 0, current_priority);
839 g_get_current_time (¤t_time);
841 /* Check to see what sources need to be dispatched */
845 hook = g_hook_first_valid (&source_list, TRUE);
848 GSource *source = (GSource *)hook;
850 if ((n_ready > 0) && (source->priority > current_priority))
852 g_hook_unref (&source_list, hook);
855 if (G_HOOK_IN_CALL (hook) && !(hook->flags & G_SOURCE_CAN_RECURSE))
857 hook = g_hook_next_valid (&source_list, hook, TRUE);
861 if (!(hook->flags & G_SOURCE_READY))
863 gboolean (*check) (gpointer source_data,
864 GTimeVal *current_time,
867 check = ((GSourceFuncs *) hook->func)->check;
868 in_check_or_prepare++;
869 G_UNLOCK (main_loop);
871 if ((*check) (source->source_data, ¤t_time, source->hook.data))
872 hook->flags |= G_SOURCE_READY;
875 in_check_or_prepare--;
878 if (hook->flags & G_SOURCE_READY)
882 hook->flags &= ~G_SOURCE_READY;
883 g_hook_ref (&source_list, hook);
884 pending_dispatches = g_slist_prepend (pending_dispatches, source);
885 current_priority = source->priority;
890 g_hook_unref (&source_list, hook);
891 G_UNLOCK (main_loop);
897 hook = g_hook_next_valid (&source_list, hook, TRUE);
900 /* Now invoke the callbacks */
902 if (pending_dispatches)
904 pending_dispatches = g_slist_reverse (pending_dispatches);
905 g_main_dispatch (¤t_time);
909 G_UNLOCK (main_loop);
914 /* See if any events are pending
917 g_main_pending (void)
919 return in_check_or_prepare ? FALSE : g_main_iterate (FALSE, FALSE);
922 /* Run a single iteration of the mainloop. If block is FALSE,
926 g_main_iteration (gboolean block)
928 if (in_check_or_prepare)
930 g_warning ("g_main_iteration(): called recursively from within a source's check() or "
931 "prepare() member or from a second thread, iteration not possible");
935 return g_main_iterate (block, TRUE);
939 g_main_new (gboolean is_running)
943 loop = g_new0 (GMainLoop, 1);
944 loop->is_running = is_running != FALSE;
950 g_main_run (GMainLoop *loop)
952 g_return_if_fail (loop != NULL);
954 if (in_check_or_prepare)
956 g_warning ("g_main_run(): called recursively from within a source's check() or "
957 "prepare() member or from a second thread, iteration not possible");
961 loop->is_running = TRUE;
962 while (loop->is_running)
963 g_main_iterate (TRUE, TRUE);
967 g_main_quit (GMainLoop *loop)
969 g_return_if_fail (loop != NULL);
971 loop->is_running = FALSE;
975 g_main_destroy (GMainLoop *loop)
977 g_return_if_fail (loop != NULL);
983 g_main_is_running (GMainLoop *loop)
985 g_return_val_if_fail (loop != NULL, FALSE);
987 return loop->is_running;
990 /* HOLDS: main_loop_lock */
992 g_main_poll (gint timeout,
993 gboolean use_priority,
996 #ifdef G_MAIN_POLL_DEBUG
1004 #ifdef G_THREADS_ENABLED
1006 if (wake_up_pipe[0] < 0)
1008 if (pipe (wake_up_pipe) < 0)
1009 g_error ("Cannot create pipe main loop wake-up: %s\n",
1010 g_strerror (errno));
1012 wake_up_rec.fd = wake_up_pipe[0];
1013 wake_up_rec.events = G_IO_IN;
1014 g_main_add_poll_unlocked (0, &wake_up_rec);
1017 if (wake_up_semaphore == NULL)
1019 if ((wake_up_semaphore = CreateSemaphore (NULL, 0, 100, NULL)) == NULL)
1020 g_error ("Cannot create wake-up semaphore: %s", g_win32_error_message (GetLastError ()));
1021 wake_up_rec.fd = (gint) wake_up_semaphore;
1022 wake_up_rec.events = G_IO_IN;
1023 #ifdef G_MAIN_POLL_DEBUG
1024 g_print ("wake-up semaphore: %#x\n", (guint) wake_up_semaphore);
1026 g_main_add_poll_unlocked (0, &wake_up_rec);
1030 fd_array = g_new (GPollFD, n_poll_records);
1032 pollrec = poll_records;
1034 while (pollrec && (!use_priority || priority >= pollrec->priority))
1036 if (pollrec->fd->events)
1038 fd_array[i].fd = pollrec->fd->fd;
1039 /* In direct contradiction to the Unix98 spec, IRIX runs into
1040 * difficulty if you pass in POLLERR, POLLHUP or POLLNVAL
1041 * flags in the events field of the pollfd while it should
1042 * just ignoring them. So we mask them out here.
1044 fd_array[i].events = pollrec->fd->events & ~(G_IO_ERR|G_IO_HUP|G_IO_NVAL);
1045 fd_array[i].revents = 0;
1049 pollrec = pollrec->next;
1051 #ifdef G_THREADS_ENABLED
1052 poll_waiting = TRUE;
1053 poll_changed = FALSE;
1057 if (npoll || timeout != 0)
1059 #ifdef G_MAIN_POLL_DEBUG
1060 g_print ("g_main_poll(%d) timeout: %d\n", npoll, timeout);
1061 poll_timer = g_timer_new ();
1064 G_UNLOCK (main_loop);
1065 if ((*poll_func) (fd_array, npoll, timeout) < 0)
1066 g_warning ("poll(2) failed due to: %s.",
1067 g_strerror (errno));
1070 #ifdef G_MAIN_POLL_DEBUG
1071 g_print ("g_main_poll(%d) timeout: %d - elapsed %12.10f seconds",
1074 g_timer_elapsed (poll_timer, NULL));
1075 g_timer_destroy (poll_timer);
1076 pollrec = poll_records;
1080 if (pollrec->fd->events)
1082 if (fd_array[i].revents)
1084 g_print (" [%d:", fd_array[i].fd);
1085 if (fd_array[i].revents & G_IO_IN)
1087 if (fd_array[i].revents & G_IO_OUT)
1089 if (fd_array[i].revents & G_IO_PRI)
1091 if (fd_array[i].revents & G_IO_ERR)
1093 if (fd_array[i].revents & G_IO_HUP)
1095 if (fd_array[i].revents & G_IO_NVAL)
1101 pollrec = pollrec->next;
1105 } /* if (npoll || timeout != 0) */
1107 #ifdef G_THREADS_ENABLED
1112 read (wake_up_pipe[0], &c, 1);
1116 poll_waiting = FALSE;
1118 /* If the set of poll file descriptors changed, bail out
1119 * and let the main loop rerun
1128 pollrec = poll_records;
1132 if (pollrec->fd->events)
1134 pollrec->fd->revents = fd_array[i].revents;
1137 pollrec = pollrec->next;
1144 g_main_add_poll (GPollFD *fd,
1148 g_main_add_poll_unlocked (priority, fd);
1149 G_UNLOCK (main_loop);
1152 /* HOLDS: main_loop_lock */
1154 g_main_add_poll_unlocked (gint priority,
1157 GPollRec *lastrec, *pollrec, *newrec;
1160 poll_chunk = g_mem_chunk_create (GPollRec, 32, G_ALLOC_ONLY);
1164 newrec = poll_free_list;
1165 poll_free_list = newrec->next;
1168 newrec = g_chunk_new (GPollRec, poll_chunk);
1171 newrec->priority = priority;
1174 pollrec = poll_records;
1175 while (pollrec && priority >= pollrec->priority)
1178 pollrec = pollrec->next;
1182 lastrec->next = newrec;
1184 poll_records = newrec;
1186 newrec->next = pollrec;
1190 #ifdef G_THREADS_ENABLED
1191 poll_changed = TRUE;
1193 /* Now wake up the main loop if it is waiting in the poll() */
1199 g_main_remove_poll (GPollFD *fd)
1201 GPollRec *pollrec, *lastrec;
1206 pollrec = poll_records;
1210 if (pollrec->fd == fd)
1212 if (lastrec != NULL)
1213 lastrec->next = pollrec->next;
1215 poll_records = pollrec->next;
1217 #ifdef ENABLE_GC_FRIENDLY
1219 #endif /* ENABLE_GC_FRIENDLY */
1221 pollrec->next = poll_free_list;
1222 poll_free_list = pollrec;
1228 pollrec = pollrec->next;
1231 #ifdef G_THREADS_ENABLED
1232 poll_changed = TRUE;
1234 /* Now wake up the main loop if it is waiting in the poll() */
1238 G_UNLOCK (main_loop);
1242 g_main_set_poll_func (GPollFunc func)
1248 poll_func = (GPollFunc) poll;
1250 poll_func = (GPollFunc) g_poll;
1256 /* Useful on other platforms, too? */
1259 g_main_win32_get_poll_func (void)
1266 /* Wake the main loop up from a poll() */
1268 g_main_wakeup (void)
1270 #ifdef G_THREADS_ENABLED
1273 poll_waiting = FALSE;
1275 write (wake_up_pipe[1], "A", 1);
1277 ReleaseSemaphore (wake_up_semaphore, 1, NULL);
1286 g_timeout_set_expiration (GTimeoutData *data,
1287 GTimeVal *current_time)
1289 guint seconds = data->interval / 1000;
1290 guint msecs = data->interval - seconds * 1000;
1292 data->expiration.tv_sec = current_time->tv_sec + seconds;
1293 data->expiration.tv_usec = current_time->tv_usec + msecs * 1000;
1294 if (data->expiration.tv_usec >= 1000000)
1296 data->expiration.tv_usec -= 1000000;
1297 data->expiration.tv_sec++;
1302 g_timeout_prepare (gpointer source_data,
1303 GTimeVal *current_time,
1308 GTimeoutData *data = source_data;
1310 msec = ((data->expiration.tv_sec - current_time->tv_sec) * 1000 +
1311 (data->expiration.tv_usec - current_time->tv_usec) / 1000);
1315 else if (msec > data->interval)
1317 /* The system time has been set backwards, so we
1318 * reset the expiration time to now + data->interval;
1319 * this at least avoids hanging for long periods of time.
1321 g_timeout_set_expiration (data, current_time);
1322 msec = data->interval;
1331 g_timeout_check (gpointer source_data,
1332 GTimeVal *current_time,
1335 GTimeoutData *data = source_data;
1337 return ((data->expiration.tv_sec < current_time->tv_sec) ||
1338 ((data->expiration.tv_sec == current_time->tv_sec) &&
1339 (data->expiration.tv_usec <= current_time->tv_usec)));
1343 g_timeout_dispatch (gpointer source_data,
1344 GTimeVal *dispatch_time,
1347 GTimeoutData *data = source_data;
1349 if (data->callback (user_data))
1351 g_timeout_set_expiration (data, dispatch_time);
1360 g_timeout_add_full (gint priority,
1362 GSourceFunc function,
1364 GDestroyNotify notify)
1366 GTimeoutData *timeout_data = g_new (GTimeoutData, 1);
1367 GTimeVal current_time;
1369 timeout_data->interval = interval;
1370 timeout_data->callback = function;
1371 g_get_current_time (¤t_time);
1373 g_timeout_set_expiration (timeout_data, ¤t_time);
1375 return g_source_add (priority, FALSE, &timeout_funcs, timeout_data, data, notify);
1379 g_timeout_add (guint32 interval,
1380 GSourceFunc function,
1383 return g_timeout_add_full (G_PRIORITY_DEFAULT,
1384 interval, function, data, NULL);
1387 /* Idle functions */
1390 g_idle_prepare (gpointer source_data,
1391 GTimeVal *current_time,
1401 g_idle_check (gpointer source_data,
1402 GTimeVal *current_time,
1409 g_idle_dispatch (gpointer source_data,
1410 GTimeVal *dispatch_time,
1413 GSourceFunc func = source_data;
1415 return func (user_data);
1419 g_idle_add_full (gint priority,
1420 GSourceFunc function,
1422 GDestroyNotify notify)
1424 g_return_val_if_fail (function != NULL, 0);
1426 return g_source_add (priority, FALSE, &idle_funcs, function, data, notify);
1430 g_idle_add (GSourceFunc function,
1433 return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, function, data, NULL);
1437 g_idle_remove_by_data (gpointer data)
1439 return g_source_remove_by_funcs_user_data (&idle_funcs, data);