summaryrefslogtreecommitdiff
path: root/gmain.c
diff options
context:
space:
mode:
authorTim Janik <timj@gtk.org>1999-07-24 18:50:58 +0000
committerTim Janik <timj@src.gnome.org>1999-07-24 18:50:58 +0000
commit87c7aeb93bd654776f59805a342ad913031034f3 (patch)
tree4f43e0cefcbe83a51ffe9aeb24f3386f519a071d /gmain.c
parentc8a28b935ca605ece11c65564ad1d3918786dd07 (diff)
downloadglib-87c7aeb93bd654776f59805a342ad913031034f3.tar.gz
18:36. incorporated proposed cleanups from gtk-devel-list.
Sat Jul 24 20:11:35 1999 Tim Janik <timj@gtk.org> * merged GLib 1.3.0 with glib-1.2.3 from Fri Jul 16 22:18:36. * incorporated proposed cleanups from gtk-devel-list. * bumped version number to GLib-1.3.1 * glib.h: * gqueue.c: * gstring.c: * glist.c: removed string tokenisation (we got g_strsplit() and g_strjoin() already) and readline functions. s/g_list_delete/g_list_delete_link. implemented g_slist_delete_link. removed notion of g_ATEXIT() macro in glib.h, this is an *internal* macro, g_atexit() is provided for public consumption. added GTrashStack inline utility functions. reimplement double eneded queues. removed GStack implementation, people can use a queue or a (singly) linked list for this task. deprecated g_strescape(), we need the SunOS variants here. * gdate.c: added DEBUG_MSG() macro to wrap old messages. * *.*: CVS merges. * upgrade to libtool 1.3.3.
Diffstat (limited to 'gmain.c')
-rw-r--r--gmain.c207
1 files changed, 167 insertions, 40 deletions
diff --git a/gmain.c b/gmain.c
index c95dc2dd0..20b1afb91 100644
--- a/gmain.c
+++ b/gmain.c
@@ -33,6 +33,11 @@
#include "config.h"
+/* uncomment the next line to get poll() debugging info */
+/* #define G_MAIN_POLL_DEBUG */
+
+
+
#include "glib.h"
#include <sys/types.h>
#include <time.h>
@@ -107,20 +112,25 @@ static void g_main_poll (gint timeout,
gint priority);
static void g_main_add_poll_unlocked (gint priority,
GPollFD *fd);
+static void g_main_wakeup (void);
static gboolean g_timeout_prepare (gpointer source_data,
GTimeVal *current_time,
- gint *timeout);
+ gint *timeout,
+ gpointer user_data);
static gboolean g_timeout_check (gpointer source_data,
- GTimeVal *current_time);
+ GTimeVal *current_time,
+ gpointer user_data);
static gboolean g_timeout_dispatch (gpointer source_data,
GTimeVal *current_time,
gpointer user_data);
static gboolean g_idle_prepare (gpointer source_data,
GTimeVal *current_time,
- gint *timeout);
+ gint *timeout,
+ gpointer user_data);
static gboolean g_idle_check (gpointer source_data,
- GTimeVal *current_time);
+ GTimeVal *current_time,
+ gpointer user_data);
static gboolean g_idle_dispatch (gpointer source_data,
GTimeVal *current_time,
gpointer user_data);
@@ -167,9 +177,16 @@ static HANDLE wake_up_semaphore = NULL;
#endif /* NATIVE_WIN32 */
static GPollFD wake_up_rec;
static gboolean poll_waiting = FALSE;
+
+/* Flag indicating whether the set of fd's changed during a poll */
+static gboolean poll_changed = FALSE;
#endif /* G_THREADS_ENABLED */
#ifdef HAVE_POLL
+/* SunOS has poll, but doesn't provide a prototype. */
+# if defined (sun) && !defined (__SVR4)
+extern gint poll (GPollFD *ufds, guint nfsd, gint timeout);
+# endif /* !sun */
static GPollFunc poll_func = (GPollFunc) poll;
#else /* !HAVE_POLL */
#ifdef NATIVE_WIN32
@@ -329,6 +346,9 @@ g_poll (GPollFD *fds, guint nfds, gint timeout)
#ifndef NO_FD_SET
# define SELECT_MASK fd_set
#else /* !NO_FD_SET */
+# ifndef _AIX
+typedef long fd_mask;
+# endif /* _AIX */
# ifdef _IBMR2
# define SELECT_MASK void
# else /* !_IBMR2 */
@@ -467,17 +487,9 @@ g_source_add (gint priority,
#ifdef G_THREADS_ENABLED
/* Now wake up the main loop if it is waiting in the poll() */
-
- if (poll_waiting)
- {
- poll_waiting = FALSE;
-#ifndef NATIVE_WIN32
- write (wake_up_pipe[1], "A", 1);
-#else
- ReleaseSemaphore (wake_up_semaphore, 1, NULL);
-#endif
- }
+ g_main_wakeup ();
#endif
+
G_UNLOCK (main_loop);
return return_val;
@@ -706,6 +718,15 @@ g_main_iterate (gboolean block,
g_get_current_time (&current_time);
G_LOCK (main_loop);
+
+#ifdef G_THREADS_ENABLED
+ if (poll_waiting)
+ {
+ g_warning("g_main_iterate(): main loop already active in another thread");
+ G_UNLOCK (main_loop);
+ return FALSE;
+ }
+#endif G_THREADS_ENABLED
/* If recursing, finish up current dispatch, before starting over */
if (pending_dispatches)
@@ -725,7 +746,7 @@ g_main_iterate (gboolean block,
hook = g_hook_first_valid (&source_list, TRUE);
while (hook)
{
- GSource *source = (GSource *)hook;
+ GSource *source = (GSource*) hook;
gint source_timeout = -1;
if ((n_ready > 0) && (source->priority > current_priority))
@@ -743,13 +764,14 @@ g_main_iterate (gboolean block,
{
gboolean (*prepare) (gpointer source_data,
GTimeVal *current_time,
- gint *timeout);
+ gint *timeout,
+ gpointer user_data);
prepare = ((GSourceFuncs *) hook->func)->prepare;
in_check_or_prepare++;
G_UNLOCK (main_loop);
- if ((*prepare) (source->source_data, &current_time, &source_timeout))
+ if ((*prepare) (source->source_data, &current_time, &source_timeout, source->hook.data))
hook->flags |= G_SOURCE_READY;
G_LOCK (main_loop);
@@ -811,13 +833,14 @@ g_main_iterate (gboolean block,
if (!(hook->flags & G_SOURCE_READY))
{
gboolean (*check) (gpointer source_data,
- GTimeVal *current_time);
+ GTimeVal *current_time,
+ gpointer user_data);
check = ((GSourceFuncs *) hook->func)->check;
in_check_or_prepare++;
G_UNLOCK (main_loop);
- if ((*check) (source->source_data, &current_time))
+ if ((*check) (source->source_data, &current_time, source->hook.data))
hook->flags |= G_SOURCE_READY;
G_LOCK (main_loop);
@@ -845,7 +868,7 @@ g_main_iterate (gboolean block,
hook = g_hook_next_valid (&source_list, hook, TRUE);
}
-
+
/* Now invoke the callbacks */
if (pending_dispatches)
@@ -906,7 +929,7 @@ g_main_run (GMainLoop *loop)
"prepare() member or from a second thread, iteration not possible");
return;
}
-
+
loop->is_running = TRUE;
while (loop->is_running)
g_main_iterate (TRUE, TRUE);
@@ -942,11 +965,14 @@ g_main_poll (gint timeout,
gboolean use_priority,
gint priority)
{
+#ifdef G_MAIN_POLL_DEBUG
+ GTimer *poll_timer;
+#endif
GPollFD *fd_array;
GPollRec *pollrec;
-
gint i;
gint npoll;
+
#ifdef G_THREADS_ENABLED
#ifndef NATIVE_WIN32
if (wake_up_pipe[0] < 0)
@@ -976,21 +1002,75 @@ g_main_poll (gint timeout,
i = 0;
while (pollrec && (!use_priority || priority >= pollrec->priority))
{
- fd_array[i].fd = pollrec->fd->fd;
- fd_array[i].events = pollrec->fd->events;
- fd_array[i].revents = 0;
-
+ if (pollrec->fd->events)
+ {
+ fd_array[i].fd = pollrec->fd->fd;
+ /* In direct contradiction to the Unix98 spec, IRIX runs into
+ * difficulty if you pass in POLLERR, POLLHUP or POLLNVAL
+ * flags in the events field of the pollfd while it should
+ * just ignoring them. So we mask them out here.
+ */
+ fd_array[i].events = pollrec->fd->events & ~(G_IO_ERR|G_IO_HUP|G_IO_NVAL);
+ fd_array[i].revents = 0;
+ i++;
+ }
+
pollrec = pollrec->next;
- i++;
}
#ifdef G_THREADS_ENABLED
poll_waiting = TRUE;
+ poll_changed = FALSE;
#endif
- G_UNLOCK (main_loop);
+
npoll = i;
- (*poll_func) (fd_array, npoll, timeout);
- G_LOCK (main_loop);
-
+ if (npoll || timeout != 0)
+ {
+#ifdef G_MAIN_POLL_DEBUG
+ g_print ("g_main_poll(%d) timeout: %d\r", npoll, timeout);
+ poll_timer = g_timer_new ();
+#endif
+
+ G_UNLOCK (main_loop);
+ (*poll_func) (fd_array, npoll, timeout);
+ G_LOCK (main_loop);
+
+#ifdef G_MAIN_POLL_DEBUG
+ g_print ("g_main_poll(%d) timeout: %d - elapsed %12.10f seconds",
+ npoll,
+ timeout,
+ g_timer_elapsed (poll_timer, NULL));
+ g_timer_destroy (poll_timer);
+ pollrec = poll_records;
+ i = 0;
+ while (i < npoll)
+ {
+ if (pollrec->fd->events)
+ {
+ if (fd_array[i].revents)
+ {
+ g_print (" [%d:", fd_array[i].fd);
+ if (fd_array[i].revents & G_IO_IN)
+ g_print ("i");
+ if (fd_array[i].revents & G_IO_OUT)
+ g_print ("o");
+ if (fd_array[i].revents & G_IO_PRI)
+ g_print ("p");
+ if (fd_array[i].revents & G_IO_ERR)
+ g_print ("e");
+ if (fd_array[i].revents & G_IO_HUP)
+ g_print ("h");
+ if (fd_array[i].revents & G_IO_NVAL)
+ g_print ("n");
+ g_print ("]");
+ }
+ i++;
+ }
+ pollrec = pollrec->next;
+ }
+ g_print ("\n");
+#endif
+ } /* if (npoll || timeout != 0) */
+
#ifdef G_THREADS_ENABLED
if (!poll_waiting)
{
@@ -1001,15 +1081,27 @@ g_main_poll (gint timeout,
}
else
poll_waiting = FALSE;
+
+ /* If the set of poll file descriptors changed, bail out
+ * and let the main loop rerun
+ */
+ if (poll_changed)
+ {
+ g_free (fd_array);
+ return;
+ }
#endif
pollrec = poll_records;
i = 0;
while (i < npoll)
{
- pollrec->fd->revents = fd_array[i].revents;
+ if (pollrec->fd->events)
+ {
+ pollrec->fd->revents = fd_array[i].revents;
+ i++;
+ }
pollrec = pollrec->next;
- i++;
}
g_free (fd_array);
@@ -1061,6 +1153,13 @@ g_main_add_poll_unlocked (gint priority,
newrec->next = pollrec;
n_poll_records++;
+
+#ifdef G_THREADS_ENABLED
+ poll_changed = TRUE;
+
+ /* Now wake up the main loop if it is waiting in the poll() */
+ g_main_wakeup ();
+#endif
}
void
@@ -1092,6 +1191,13 @@ g_main_remove_poll (GPollFD *fd)
pollrec = pollrec->next;
}
+#ifdef G_THREADS_ENABLED
+ poll_changed = TRUE;
+
+ /* Now wake up the main loop if it is waiting in the poll() */
+ g_main_wakeup ();
+#endif
+
G_UNLOCK (main_loop);
}
@@ -1108,12 +1214,30 @@ g_main_set_poll_func (GPollFunc func)
#endif
}
+/* Wake the main loop up from a poll() */
+static void
+g_main_wakeup (void)
+{
+#ifdef G_THREADS_ENABLED
+ if (poll_waiting)
+ {
+ poll_waiting = FALSE;
+#ifndef NATIVE_WIN32
+ write (wake_up_pipe[1], "A", 1);
+#else
+ ReleaseSemaphore (wake_up_semaphore, 1, NULL);
+#endif
+ }
+#endif
+}
+
/* Timeouts */
static gboolean
-g_timeout_prepare (gpointer source_data,
+g_timeout_prepare (gpointer source_data,
GTimeVal *current_time,
- gint *timeout)
+ gint *timeout,
+ gpointer user_data)
{
glong msec;
GTimeoutData *data = source_data;
@@ -1127,8 +1251,9 @@ g_timeout_prepare (gpointer source_data,
}
static gboolean
-g_timeout_check (gpointer source_data,
- GTimeVal *current_time)
+g_timeout_check (gpointer source_data,
+ GTimeVal *current_time,
+ gpointer user_data)
{
GTimeoutData *data = source_data;
@@ -1203,9 +1328,10 @@ g_timeout_add (guint32 interval,
/* Idle functions */
static gboolean
-g_idle_prepare (gpointer source_data,
+g_idle_prepare (gpointer source_data,
GTimeVal *current_time,
- gint *timeout)
+ gint *timeout,
+ gpointer user_data)
{
timeout = 0;
return TRUE;
@@ -1213,7 +1339,8 @@ g_idle_prepare (gpointer source_data,
static gboolean
g_idle_check (gpointer source_data,
- GTimeVal *current_time)
+ GTimeVal *current_time,
+ gpointer user_data)
{
return TRUE;
}