summaryrefslogtreecommitdiff
path: root/gmain.c
diff options
context:
space:
mode:
authorTor Lillqvist <tml@iki.fi>2000-07-29 20:59:07 +0000
committerTor Lillqvist <tml@src.gnome.org>2000-07-29 20:59:07 +0000
commitb965bb5db1732cee8e0ed92d6484921a1431d6a9 (patch)
treee7f697681ba7c93210a23d8139117ce83365e675 /gmain.c
parentd33887428e66f8619f6d809fbbed2fdd8d02bcac (diff)
downloadglib-b965bb5db1732cee8e0ed92d6484921a1431d6a9.tar.gz
Finally, a new and improved IO Channel and condition watch implementation
2000-07-30 Tor Lillqvist <tml@iki.fi> Finally, a new and improved IO Channel and condition watch implementation for Win32. Based on code provided by Craig Setera. When watching file descriptors, for which there is no select() like functionality on Win32 that would work on all Win32 platforms for all types of file descriptors (including anonymous pipes), we start a new thread that blocks while trying to read from the file descriptor. When the read returns, a Win32 Event is signalled that the polling routine eventually notices. Meanwhile, the data being read is stored in a circular buffer, from where the IO channel's read() method picks it up. If the buffer fills up the reading thread has to wait for space becoming available. For this another Win32 Event is used. The IO Channel's read() method signals this when it has read some data out of the buffer. The separate reader thread(s), and the circular buffer(s) with associated events mean lots of possibilities for fun parallellism errors. But it seems to work OK, i.e. GIMP runs. * gmain.c: Small changes to the Win32 polling function. (g_main_win32_get_poll_func): New function. Perhaps it would be a good idea to provide this on all platforms. * giowin32.c: The bulk of the new implementation. (g_io_channel_win32_wait_for_condition): New function. To be used where on Unix one does a select() on the channel's fd, like libgimp's gimp_extension_process(). Could be provided on all platforms. * glib.h: Update documentation for IO Channels on Win32. Remove the declarations for the as of now obsolete old functions related to IO Channels for pipes with "wakeup" messages. * glib.def: Some new functions. * tests/gio-test.c: New file, to test GIOChannel and main loop. * tests/Makefile.am * tests/makefile.mingw.in: Add it.
Diffstat (limited to 'gmain.c')
-rw-r--r--gmain.c104
1 files changed, 72 insertions, 32 deletions
diff --git a/gmain.c b/gmain.c
index 23a0c30d2..a3404a6e9 100644
--- a/gmain.c
+++ b/gmain.c
@@ -36,8 +36,6 @@
/* uncomment the next line to get poll() debugging info */
/* #define G_MAIN_POLL_DEBUG */
-
-
#include "glib.h"
#include <sys/types.h>
#include <time.h>
@@ -192,34 +190,39 @@ static GPollFunc poll_func = (GPollFunc) poll;
#ifdef G_OS_WIN32
static gint
-g_poll (GPollFD *fds, guint nfds, gint timeout)
+g_poll (GPollFD *fds,
+ guint nfds,
+ gint timeout)
{
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+ gboolean poll_msgs = FALSE;
GPollFD *f;
DWORD ready;
MSG msg;
UINT timer;
- LONG prevcnt;
- gint poll_msgs = -1;
gint nhandles = 0;
for (f = fds; f < &fds[nfds]; ++f)
if (f->fd >= 0)
{
if (f->events & G_IO_IN)
- if (f->fd == G_WIN32_MSG_HANDLE)
- poll_msgs = f - fds;
- else
- {
- /* g_print ("g_poll: waiting for handle %#x\n", f->fd); */
- handles[nhandles++] = (HANDLE) f->fd;
- }
+ {
+ if (f->fd == G_WIN32_MSG_HANDLE)
+ poll_msgs = TRUE;
+ else
+ {
+#ifdef G_MAIN_POLL_DEBUG
+ g_print ("g_poll: waiting for %#x\n", f->fd);
+#endif
+ handles[nhandles++] = (HANDLE) f->fd;
+ }
+ }
}
if (timeout == -1)
timeout = INFINITE;
- if (poll_msgs >= 0)
+ if (poll_msgs)
{
/* Waiting for messages, and maybe events */
if (nhandles == 0)
@@ -229,7 +232,9 @@ g_poll (GPollFD *fds, guint nfds, gint timeout)
/* Waiting just for messages, infinite timeout
* -> Use PeekMessage, then WaitMessage
*/
- /* g_print ("WaitMessage, PeekMessage\n"); */
+#ifdef G_MAIN_POLL_DEBUG
+ g_print ("PeekMessage, then WaitMessage\n");
+#endif
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
ready = WAIT_OBJECT_0;
else if (!WaitMessage ())
@@ -241,7 +246,9 @@ g_poll (GPollFD *fds, guint nfds, gint timeout)
/* Waiting just for messages, zero timeout
* -> Use PeekMessage
*/
- /* g_print ("PeekMessage\n"); */
+#ifdef G_MAIN_POLL_DEBUG
+ g_print ("PeekMessage\n");
+#endif
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
ready = WAIT_OBJECT_0;
else
@@ -253,17 +260,22 @@ g_poll (GPollFD *fds, guint nfds, gint timeout)
* -> First try PeekMessage, then set a timer, wait for message,
* kill timer, use PeekMessage
*/
- /* g_print ("PeekMessage\n"); */
+#ifdef G_MAIN_POLL_DEBUG
+ g_print ("PeekMessage\n");
+#endif
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
ready = WAIT_OBJECT_0;
else if ((timer = SetTimer (NULL, 0, timeout, NULL)) == 0)
g_warning ("g_poll: SetTimer failed");
else
{
- /* g_print ("WaitMessage\n"); */
+#ifdef G_MAIN_POLL_DEBUG
+ g_print ("WaitMessage\n");
+#endif
WaitMessage ();
KillTimer (NULL, timer);
- if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
+ if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)
+ && msg.message != WM_TIMER)
ready = WAIT_OBJECT_0;
else
ready = WAIT_TIMEOUT;
@@ -275,10 +287,12 @@ g_poll (GPollFD *fds, guint nfds, gint timeout)
/* Wait for either message or event
* -> Use MsgWaitForMultipleObjects
*/
- /* g_print ("MsgWaitForMultipleObjects(%d, %d)\n", nhandles, timeout); */
+#ifdef G_MAIN_POLL_DEBUG
+ g_print ("MsgWaitForMultipleObjects(%d, %d)\n", nhandles, timeout);
+#endif
ready = MsgWaitForMultipleObjects (nhandles, handles, FALSE,
timeout, QS_ALLINPUT);
- /* g_print("=%d\n", ready); */
+
if (ready == WAIT_FAILED)
g_warning ("g_poll: MsgWaitForMultipleObjects failed");
}
@@ -293,9 +307,10 @@ g_poll (GPollFD *fds, guint nfds, gint timeout)
/* Wait for just events
* -> Use WaitForMultipleObjects
*/
- /* g_print ("WaitForMultipleObjects(%d, %d)\n", nhandles, timeout); */
+#ifdef G_MAIN_POLL_DEBUG
+ g_print ("WaitForMultipleObjects(%d, %d)\n", nhandles, timeout);
+#endif
ready = WaitForMultipleObjects (nhandles, handles, FALSE, timeout);
- /* g_print("=%d\n", ready); */
if (ready == WAIT_FAILED)
g_warning ("g_poll: WaitForMultipleObjects failed");
}
@@ -305,9 +320,17 @@ g_poll (GPollFD *fds, guint nfds, gint timeout)
if (ready == WAIT_FAILED)
return -1;
- else if (poll_msgs >= 0 && ready == WAIT_OBJECT_0 + nhandles)
+ else if (ready == WAIT_TIMEOUT)
+ return 0;
+ else if (poll_msgs && ready == WAIT_OBJECT_0 + nhandles)
{
- fds[poll_msgs].revents |= G_IO_IN;
+ for (f = fds; f < &fds[nfds]; ++f)
+ if (f->fd >= 0)
+ {
+ if (f->events & G_IO_IN)
+ if (f->fd == G_WIN32_MSG_HANDLE)
+ f->revents |= G_IO_IN;
+ }
}
else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)
for (f = fds; f < &fds[nfds]; ++f)
@@ -316,15 +339,19 @@ g_poll (GPollFD *fds, guint nfds, gint timeout)
&& f->fd == (gint) handles[ready - WAIT_OBJECT_0])
{
f->revents |= G_IO_IN;
- /* g_print ("event %#x\n", f->fd); */
+#ifdef G_MAIN_POLL_DEBUG
+ g_print ("g_poll: got event %#x\n", f->fd);
+#endif
+#if 0
ResetEvent ((HANDLE) f->fd);
+#endif
}
}
- if (ready == WAIT_TIMEOUT)
- return 0;
+ if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)
+ return ready - WAIT_OBJECT_0 + 1;
else
- return 1;
+ return 0;
}
#else /* !G_OS_WIN32 */
@@ -592,7 +619,6 @@ void
g_get_current_time (GTimeVal *result)
{
#ifndef G_OS_WIN32
- struct timeval r;
g_return_if_fail (result != NULL);
/*this is required on alpha, there the timeval structs are int's
@@ -608,7 +634,6 @@ g_get_current_time (GTimeVal *result)
static DWORD start_tick = 0;
static time_t start_time;
DWORD tick;
- time_t t;
g_return_if_fail (result != NULL);
@@ -992,9 +1017,12 @@ g_main_poll (gint timeout,
if (wake_up_semaphore == NULL)
{
if ((wake_up_semaphore = CreateSemaphore (NULL, 0, 100, NULL)) == NULL)
- g_error ("Cannot create wake-up semaphore: %d", GetLastError ());
+ g_error ("Cannot create wake-up semaphore: %s", g_win32_error_message (GetLastError ()));
wake_up_rec.fd = (gint) wake_up_semaphore;
wake_up_rec.events = G_IO_IN;
+#ifdef G_MAIN_POLL_DEBUG
+ g_print ("wake-up semaphore: %#x\n", (guint) wake_up_semaphore);
+#endif
g_main_add_poll_unlocked (0, &wake_up_rec);
}
#endif
@@ -1029,7 +1057,7 @@ g_main_poll (gint timeout,
if (npoll || timeout != 0)
{
#ifdef G_MAIN_POLL_DEBUG
- g_print ("g_main_poll(%d) timeout: %d\r", npoll, timeout);
+ g_print ("g_main_poll(%d) timeout: %d\n", npoll, timeout);
poll_timer = g_timer_new ();
#endif
@@ -1223,6 +1251,18 @@ g_main_set_poll_func (GPollFunc func)
#endif
}
+#ifdef G_OS_WIN32
+
+/* Useful on other platforms, too? */
+
+GPollFunc
+g_main_win32_get_poll_func (void)
+{
+ return poll_func;
+}
+
+#endif
+
/* Wake the main loop up from a poll() */
static void
g_main_wakeup (void)