summaryrefslogtreecommitdiff
path: root/glib
diff options
context:
space:
mode:
Diffstat (limited to 'glib')
-rw-r--r--glib/giowin32.c1133
-rw-r--r--glib/glib.def3
-rw-r--r--glib/glib.h66
-rw-r--r--glib/gmain.c104
4 files changed, 608 insertions, 698 deletions
diff --git a/glib/giowin32.c b/glib/giowin32.c
index 36fa82c5b..c06df4a0d 100644
--- a/glib/giowin32.c
+++ b/glib/giowin32.c
@@ -3,6 +3,7 @@
*
* giowin32.c: IO Channels for Win32.
* Copyright 1998 Owen Taylor and Tor Lillqvist
+ * Copyright 1999-2000 Tor Lillqvist and Craig Setera
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -11,7 +12,7 @@
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
@@ -24,31 +25,37 @@
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
+/* Define this to get (very) verbose logging */
+/* #define G_IO_WIN32_DEBUG */
-#include "config.h"
#include "glib.h"
+
+#include <stdlib.h>
#include <windows.h>
-#include <winsock.h> /* Not everybody has winsock2 */
+#include <winsock.h> /* Not everybody has winsock2 */
#include <fcntl.h>
#include <io.h>
+#include <process.h>
#include <errno.h>
-#include <sys/types.h>
-
-#include <stdio.h>
+#include <sys/stat.h>
typedef struct _GIOWin32Channel GIOWin32Channel;
typedef struct _GIOWin32Watch GIOWin32Watch;
-guint g_pipe_readable_msg;
+#define BUFFER_SIZE 4096
typedef enum {
G_IO_WINDOWS_MESSAGES, /* Windows messages */
- G_IO_FILE_DESC, /* Unix-like file descriptors from _open*/
- G_IO_PIPE, /* pipe, with windows messages for signalling */
- G_IO_STREAM_SOCKET /* Stream sockets */
+ G_IO_FILE_DESC, /* Unix-like file descriptors from
+ * _open() or _pipe(). Read with read().
+ * Have to create separate thread to read.
+ */
+ G_IO_STREAM_SOCKET /* Stream sockets. Similar as fds, but
+ * read with recv().
+ */
} GIOWin32ChannelType;
struct _GIOWin32Channel {
@@ -58,19 +65,49 @@ struct _GIOWin32Channel {
* as provided by WinSock.
*/
GIOWin32ChannelType type;
-
+
/* This is used by G_IO_WINDOWS_MESSAGES channels */
HWND hwnd; /* handle of window, or NULL */
-
- /* This is used by G_IO_PIPE channels */
- guint peer; /* thread id of reader */
- guint peer_fd; /* fd in the reader */
- guint offset; /* counter of accumulated bytes */
- guint need_wakeups; /* in output channels whether the
- * reader needs wakeups
+
+ /* Following fields used by fd and socket channels for input */
+
+ /* Data is kept in a circular buffer. To be able to distinguish between
+ * empty and full buffer, we cannot fill it completely, but have to
+ * leave a one character gap.
+ *
+ * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
+ *
+ * Empty: wrp == rdp
+ * Full: (wrp + 1) % BUFFER_SIZE == rdp
+ * Partial: otherwise
+ */
+ guchar *buffer; /* (Circular) buffer */
+ gint wrp, rdp; /* Buffer indices for writing and reading */
+ gboolean running; /* Is reader thread running. FALSE if
+ * EOF has been reached.
*/
+ guint thread_id; /* If non-NULL has a reader thread, or has
+ * had.*/
+ HANDLE data_avail_event;
+ HANDLE space_avail_event;
+ CRITICAL_SECTION mutex;
+
+ /* Function that actually reads from fd */
+ int (*reader) (int fd, guchar *buf, int len);
};
+#define LOCK(mutex) EnterCriticalSection (&mutex)
+#define UNLOCK(mutex) LeaveCriticalSection (&mutex)
+
+/* Temporarilyu change a PRINT to PRINT_ to get just *that* message */
+#define PRINT_(x) g_print x
+
+#ifdef G_IO_WIN32_DEBUG
+#define PRINT(x) PRINT_(x)
+#else
+#define PRINT(x)
+#endif
+
struct _GIOWin32Watch {
GPollFD pollfd;
GIOChannel *channel;
@@ -78,346 +115,314 @@ struct _GIOWin32Watch {
GIOFunc callback;
};
-static gboolean g_io_win32_msg_prepare (gpointer source_data,
- GTimeVal *current_time,
- gint *timeout);
-static gboolean g_io_win32_msg_check (gpointer source_data,
- GTimeVal *current_time);
-static gboolean g_io_win32_msg_dispatch (gpointer source_data,
- GTimeVal *current_time,
- gpointer user_data);
-
-static gboolean g_io_win32_fd_prepare (gpointer source_data,
- GTimeVal *current_time,
- gint *timeout);
-static gboolean g_io_win32_fd_check (gpointer source_data,
- GTimeVal *current_time);
-static gboolean g_io_win32_fd_dispatch (gpointer source_data,
- GTimeVal *current_time,
- gpointer user_data);
-
-static gboolean g_io_win32_pipe_prepare (gpointer source_data,
- GTimeVal *current_time,
- gint *timeout);
-static gboolean g_io_win32_pipe_check (gpointer source_data,
- GTimeVal *current_time);
-static gboolean g_io_win32_pipe_dispatch (gpointer source_data,
- GTimeVal *current_time,
- gpointer user_data);
-static void g_io_win32_pipe_destroy (gpointer source_data);
-
-static gboolean g_io_win32_sock_prepare (gpointer source_data,
- GTimeVal *current_time,
- gint *timeout);
-static gboolean g_io_win32_sock_check (gpointer source_data,
- GTimeVal *current_time);
-static gboolean g_io_win32_sock_dispatch (gpointer source_data,
- GTimeVal *current_time,
- gpointer user_data);
-
-static void g_io_win32_destroy (gpointer source_data);
-
-static GIOError g_io_win32_msg_read (GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_written);
-
-static GIOError g_io_win32_msg_write(GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_written);
-static GIOError g_io_win32_msg_seek (GIOChannel *channel,
- gint offset,
- GSeekType type);
-static void g_io_win32_msg_close (GIOChannel *channel);
-static guint g_io_win32_msg_add_watch (GIOChannel *channel,
- gint priority,
- GIOCondition condition,
- GIOFunc func,
- gpointer user_data,
- GDestroyNotify notify);
-
-static GIOError g_io_win32_fd_read (GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_written);
-static GIOError g_io_win32_fd_write(GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_written);
-static GIOError g_io_win32_fd_seek (GIOChannel *channel,
- gint offset,
- GSeekType type);
-static void g_io_win32_fd_close (GIOChannel *channel);
-
-static void g_io_win32_free (GIOChannel *channel);
-
-static guint g_io_win32_fd_add_watch (GIOChannel *channel,
- gint priority,
- GIOCondition condition,
- GIOFunc func,
- gpointer user_data,
- GDestroyNotify notify);
-
-static GIOError g_io_win32_no_seek (GIOChannel *channel,
- gint offset,
- GSeekType type);
-
-static GIOError g_io_win32_pipe_read (GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_written);
-static GIOError g_io_win32_pipe_write (GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_written);
-static void g_io_win32_pipe_close (GIOChannel *channel);
-static guint g_io_win32_pipe_add_watch (GIOChannel *channel,
- gint priority,
- GIOCondition condition,
- GIOFunc func,
- gpointer user_data,
- GDestroyNotify notify);
-static void g_io_win32_pipe_free (GIOChannel *channel);
-
-static GIOError g_io_win32_sock_read (GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_written);
-static GIOError g_io_win32_sock_write(GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_written);
-static void g_io_win32_sock_close (GIOChannel *channel);
-static guint g_io_win32_sock_add_watch (GIOChannel *channel,
- gint priority,
- GIOCondition condition,
- GIOFunc func,
- gpointer user_data,
- GDestroyNotify notify);
-
-GSourceFuncs win32_watch_msg_funcs = {
- g_io_win32_msg_prepare,
- g_io_win32_msg_check,
- g_io_win32_msg_dispatch,
- g_io_win32_destroy
-};
+static void
+create_events (GIOWin32Channel *channel)
+{
+ SECURITY_ATTRIBUTES sec_attrs;
+
+ sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sec_attrs.lpSecurityDescriptor = NULL;
+ sec_attrs.bInheritHandle = FALSE;
-GSourceFuncs win32_watch_fd_funcs = {
- g_io_win32_fd_prepare,
- g_io_win32_fd_check,
- g_io_win32_fd_dispatch,
- g_io_win32_destroy
-};
+ channel->data_avail_event = NULL;
+ channel->space_avail_event = NULL;
+
+ /* The data available event is manual reset, the space available event
+ * is automatic reset.
+ */
+ if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
+ || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
+ {
+ gchar *msg = g_win32_error_message (GetLastError ());
+ g_error ("Error creating event: %s", msg);
+ }
+ InitializeCriticalSection (&channel->mutex);
+}
-GSourceFuncs win32_watch_pipe_funcs = {
- g_io_win32_pipe_prepare,
- g_io_win32_pipe_check,
- g_io_win32_pipe_dispatch,
- g_io_win32_pipe_destroy
-};
+static unsigned __stdcall
+reader_thread (void *parameter)
+{
+ GIOWin32Channel *channel = parameter;
+ guchar *buffer;
+ guint nbytes;
-GSourceFuncs win32_watch_sock_funcs = {
- g_io_win32_sock_prepare,
- g_io_win32_sock_check,
- g_io_win32_sock_dispatch,
- g_io_win32_destroy
-};
+ g_io_channel_ref ((GIOChannel *) channel);
-GIOFuncs win32_channel_msg_funcs = {
- g_io_win32_msg_read,
- g_io_win32_msg_write,
- g_io_win32_no_seek,
- g_io_win32_msg_close,
- g_io_win32_msg_add_watch,
- g_io_win32_free
-};
+ PRINT (("thread %#x: starting. pid:%#x, fd:%d, data_avail:%#x, space_avail:%#x\n",
+ channel->thread_id,
+ (guint) GetCurrentProcessId (),
+ channel->fd,
+ (guint) channel->data_avail_event,
+ (guint) channel->space_avail_event));
+
+ channel->buffer = g_malloc (BUFFER_SIZE);
+ channel->rdp = channel->wrp = 0;
+ channel->running = TRUE;
-GIOFuncs win32_channel_fd_funcs = {
- g_io_win32_fd_read,
- g_io_win32_fd_write,
- g_io_win32_fd_seek,
- g_io_win32_fd_close,
- g_io_win32_fd_add_watch,
- g_io_win32_free
-};
+ SetEvent (channel->space_avail_event);
+
+ while (channel->running)
+ {
+ LOCK (channel->mutex);
+ PRINT (("thread %#x: rdp=%d, wrp=%d\n",
+ channel->thread_id, channel->rdp, channel->wrp));
+ if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
+ {
+ /* Buffer is full */
+ PRINT (("thread %#x: resetting space_available\n",
+ channel->thread_id));
+ ResetEvent (channel->space_avail_event);
+ PRINT (("thread %#x: waiting for space\n", channel->thread_id));
+ UNLOCK (channel->mutex);
+ WaitForSingleObject (channel->space_avail_event, INFINITE);
+ LOCK (channel->mutex);
+ PRINT (("thread %#x: rdp=%d, wrp=%d\n",
+ channel->thread_id, channel->rdp, channel->wrp));
+ }
+
+ buffer = channel->buffer + channel->wrp;
+
+ /* Always leave at least one byte unused gap to be able to
+ * distinguish between the full and empty condition...
+ */
+ nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
+ BUFFER_SIZE - channel->wrp);
-GIOFuncs win32_channel_pipe_funcs = {
- g_io_win32_pipe_read,
- g_io_win32_pipe_write,
- g_io_win32_no_seek,
- g_io_win32_pipe_close,
- g_io_win32_pipe_add_watch,
- g_io_win32_pipe_free
-};
+ UNLOCK (channel->mutex);
-GIOFuncs win32_channel_sock_funcs = {
- g_io_win32_sock_read,
- g_io_win32_sock_write,
- g_io_win32_no_seek,
- g_io_win32_sock_close,
- g_io_win32_sock_add_watch,
- g_io_win32_free
-};
+ nbytes = (*channel->reader) (channel->fd, buffer, nbytes);
+
+ if (nbytes <= 0)
+ break;
-#define N_WATCHED_PIPES 4
+ LOCK (channel->mutex);
+ PRINT (("thread %#x: got %d bytes, rdp=%d, wrp=%d\n",
+ channel->thread_id, nbytes, channel->rdp, channel->wrp));
+ channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
+ PRINT (("thread %#x: rdp=%d, wrp=%d, setting data available\n",
+ channel->thread_id, channel->rdp, channel->wrp));
+ SetEvent (channel->data_avail_event);
+ UNLOCK (channel->mutex);
+ }
+
+ LOCK (channel->mutex);
+ channel->running = FALSE;
+ PRINT (("thread %#x: got EOF, rdp=%d, wrp=%d, setting data available\n",
+ channel->thread_id, channel->rdp, channel->wrp));
+ SetEvent (channel->data_avail_event);
+ UNLOCK (channel->mutex);
+
+ g_io_channel_unref((GIOChannel *) channel);
+
+ /* All of the Microsoft docs say we should explicitly
+ * end the thread...
+ */
+ _endthreadex(1);
+
+ return 0;
+}
-static struct {
- gint fd;
- GIOWin32Watch *watch;
- GIOWin32Channel *channel;
- gpointer user_data;
-} watched_pipes[N_WATCHED_PIPES];
+static void
+create_reader_thread (GIOWin32Channel *channel,
+ gpointer reader)
+{
+ channel->reader = reader;
-static gint n_watched_pipes = 0;
+ if (_beginthreadex (NULL, 0, reader_thread, channel, 0,
+ &channel->thread_id) == 0)
+ g_warning ("Error creating reader thread: %s", strerror (errno));
+ WaitForSingleObject (channel->space_avail_event, INFINITE);
+}
-static gboolean
-g_io_win32_msg_prepare (gpointer source_data,
- GTimeVal *current_time,
- gint *timeout)
+static int
+buffer_read (GIOWin32Channel *channel,
+ guchar *dest,
+ guint count,
+ GIOError *error)
{
- GIOWin32Watch *data = source_data;
- GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
- MSG msg;
+ guint nbytes;
+ guint left = count;
+
+ LOCK (channel->mutex);
+ PRINT (("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
+ channel->thread_id, count, channel->rdp, channel->wrp));
+
+ while (left)
+ {
+ if (channel->rdp == channel->wrp)
+ {
+ UNLOCK (channel->mutex);
+ PRINT (("waiting for data from thread %#x\n", channel->thread_id));
+ WaitForSingleObject (channel->data_avail_event, INFINITE);
+ LOCK (channel->mutex);
+ if (channel->rdp == channel->wrp && !channel->running)
+ break;
+ }
+
+ if (channel->rdp < channel->wrp)
+ nbytes = channel->wrp - channel->rdp;
+ else
+ nbytes = BUFFER_SIZE - channel->rdp;
+ UNLOCK (channel->mutex);
+ nbytes = MIN (left, nbytes);
+ PRINT (("moving %d bytes from thread %#x\n",
+ nbytes, channel->thread_id));
+ memcpy (dest, channel->buffer + channel->rdp, nbytes);
+ dest += nbytes;
+ left -= nbytes;
+ LOCK (channel->mutex);
+ channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
+ PRINT (("setting space available for thread %#x\n", channel->thread_id));
+ SetEvent (channel->space_avail_event);
+ PRINT (("for thread %#x: rdp=%d, wrp=%d\n",
+ channel->thread_id, channel->rdp, channel->wrp));
+ if (channel->running && channel->rdp == channel->wrp)
+ {
+ PRINT (("resetting data_available of thread %#x\n",
+ channel->thread_id));
+ ResetEvent (channel->data_avail_event);
+ };
+ }
+ UNLOCK (channel->mutex);
+
+ return count - left;
+}
+static gboolean
+g_io_win32_prepare (gpointer source_data,
+ GTimeVal *current_time,
+ gint *timeout,
+ gpointer user_data)
+{
*timeout = -1;
-
- return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
+
+ return FALSE;
}
-static gboolean
-g_io_win32_msg_check (gpointer source_data,
- GTimeVal *current_time)
+static gboolean
+g_io_win32_check (gpointer source_data,
+ GTimeVal *current_time,
+ gpointer user_data)
{
GIOWin32Watch *data = source_data;
- GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
- MSG msg;
-
- return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
+ GIOWin32Channel *channel = (GIOWin32Channel *) data->channel;
+
+ /* If the thread has died, we have encountered EOF. If the buffer
+ * also is emtpty set the HUP bit.
+ */
+ if (!channel->running && channel->rdp == channel->wrp)
+ {
+ PRINT (("g_io_win32_check: setting G_IO_HUP thread %#x rdp=%d wrp=%d\n", channel->thread_id, channel->rdp, channel->wrp));
+ data->pollfd.revents |= G_IO_HUP;
+ return TRUE;
+ }
+
+ return (data->pollfd.revents & data->condition);
}
static gboolean
-g_io_win32_msg_dispatch (gpointer source_data,
- GTimeVal *current_time,
- gpointer user_data)
-
+g_io_win32_dispatch (gpointer source_data,
+ GTimeVal *current_time,
+ gpointer user_data)
+
{
GIOWin32Watch *data = source_data;
-
- return (*data->callback)(data->channel,
- data->pollfd.revents & data->condition,
- user_data);
+
+ return (*data->callback) (data->channel,
+ data->pollfd.revents & data->condition,
+ user_data);
}
static void
g_io_win32_destroy (gpointer source_data)
{
GIOWin32Watch *data = source_data;
-
+
g_main_remove_poll (&data->pollfd);
g_io_channel_unref (data->channel);
g_free (data);
}
-static gboolean
-g_io_win32_fd_prepare (gpointer source_data,
- GTimeVal *current_time,
- gint *timeout)
-{
- *timeout = -1;
-
- return FALSE;
-}
-
-static gboolean
-g_io_win32_fd_check (gpointer source_data,
- GTimeVal *current_time)
-{
- GIOWin32Watch *data = source_data;
-
- return (data->pollfd.revents & data->condition);
-}
-
-static gboolean
-g_io_win32_fd_dispatch (gpointer source_data,
- GTimeVal *current_time,
- gpointer user_data)
-
-{
- GIOWin32Watch *data = source_data;
-
- return (*data->callback)(data->channel,
- data->pollfd.revents & data->condition,
- user_data);
-}
+static GSourceFuncs win32_watch_funcs = {
+ g_io_win32_prepare,
+ g_io_win32_check,
+ g_io_win32_dispatch,
+ g_io_win32_destroy
+};
static GIOError
-g_io_win32_msg_read (GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_read)
+g_io_win32_msg_read (GIOChannel *channel,
+ gchar *buf,
+ guint count,
+ guint *bytes_read)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
- MSG msg; /* In case of alignment problems */
-
+ MSG msg; /* In case of alignment problems */
+
if (count < sizeof (MSG))
return G_IO_ERROR_INVAL;
if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
return G_IO_ERROR_AGAIN;
-
+
memmove (buf, &msg, sizeof (MSG));
*bytes_read = sizeof (MSG);
return G_IO_ERROR_NONE;
}
-
-static GIOError
-g_io_win32_msg_write(GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_written)
+
+static GIOError
+g_io_win32_msg_write (GIOChannel *channel,
+ gchar *buf,
+ guint count,
+ guint *bytes_written)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
MSG msg;
- gint result;
-
+
if (count != sizeof (MSG))
return G_IO_ERROR_INVAL;
-
+
/* In case of alignment problems */
memmove (&msg, buf, sizeof (MSG));
if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
return G_IO_ERROR_UNKNOWN;
-
+
*bytes_written = sizeof (MSG);
- return G_IO_ERROR_NONE;
+ return G_IO_ERROR_NONE;
}
-static GIOError
+static GIOError
g_io_win32_no_seek (GIOChannel *channel,
- gint offset,
- GSeekType type)
+ gint offset,
+ GSeekType type)
{
- g_warning ("g_io_win32_no_seek: unseekable IO channel type");
return G_IO_ERROR_UNKNOWN;
}
-static void
+static void
g_io_win32_msg_close (GIOChannel *channel)
{
/* Nothing to be done. Or should we set hwnd to some invalid value? */
}
-static void
+static void
g_io_win32_free (GIOChannel *channel)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+ if (win32_channel->buffer)
+ {
+ CloseHandle (win32_channel->data_avail_event);
+ CloseHandle (win32_channel->space_avail_event);
+ DeleteCriticalSection (&win32_channel->mutex);
+ }
+ g_free (win32_channel->buffer);
g_free (win32_channel);
}
-static guint
+static guint
g_io_win32_msg_add_watch (GIOChannel *channel,
gint priority,
GIOCondition condition,
@@ -426,117 +431,56 @@ g_io_win32_msg_add_watch (GIOChannel *channel,
GDestroyNotify notify)
{
GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
- GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
watch->channel = channel;
g_io_channel_ref (channel);
-
+
watch->callback = func;
watch->condition = condition;
-
+
watch->pollfd.fd = G_WIN32_MSG_HANDLE;
watch->pollfd.events = condition;
-
+
g_main_add_poll (&watch->pollfd, priority);
-
- return g_source_add (priority, TRUE, &win32_watch_msg_funcs,
+
+ return g_source_add (priority, TRUE, &win32_watch_funcs,
watch, user_data, notify);
}
-static gboolean
-g_io_win32_pipe_prepare (gpointer source_data,
- GTimeVal *current_time,
- gint *timeout)
-{
- *timeout = -1;
-
- return FALSE;
-}
-
-static gboolean
-g_io_win32_pipe_check (gpointer source_data,
- GTimeVal *current_time)
-{
- GIOWin32Watch *data = source_data;
- return FALSE;
-}
-
-static gboolean
-g_io_win32_pipe_dispatch (gpointer source_data,
- GTimeVal *current_time,
- gpointer user_data)
-
-{
- GIOWin32Watch *data = source_data;
-
- return (*data->callback)(data->channel,
- data->pollfd.revents & data->condition,
- user_data);
-}
-
-static void
-g_io_win32_pipe_destroy (gpointer source_data)
-{
- GIOWin32Watch *data = source_data;
-
- g_io_channel_unref (data->channel);
- g_free (data);
-}
-
-static gboolean
-g_io_win32_sock_prepare (gpointer source_data,
- GTimeVal *current_time,
- gint *timeout)
-{
- *timeout = -1;
-
- return FALSE;
-}
-
-static gboolean
-g_io_win32_sock_check (gpointer source_data,
- GTimeVal *current_time)
-{
- GIOWin32Watch *data = source_data;
-
- return (data->pollfd.revents & data->condition);
-}
-
-static gboolean
-g_io_win32_sock_dispatch (gpointer source_data,
- GTimeVal *current_time,
- gpointer user_data)
-
-{
- GIOWin32Watch *data = source_data;
-
- return (*data->callback)(data->channel,
- data->pollfd.revents & data->condition,
- user_data);
-}
-
static GIOError
-g_io_win32_fd_read (GIOChannel *channel,
- gchar *buf,
+g_io_win32_fd_read (GIOChannel *channel,
+ gchar *buf,
guint count,
guint *bytes_read)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
gint result;
+ GIOError error;
+
+ if (win32_channel->thread_id)
+ {
+ result = buffer_read (win32_channel, buf, count, &error);
+ if (result < 0)
+ {
+ *bytes_read = 0;
+ return error;
+ }
+ else
+ {
+ *bytes_read = result;
+ return G_IO_ERROR_NONE;
+ }
+ }
result = read (win32_channel->fd, buf, count);
+
if (result < 0)
{
*bytes_read = 0;
- switch (errno)
- {
- case EINVAL:
- return G_IO_ERROR_INVAL;
- case EAGAIN:
- return G_IO_ERROR_AGAIN;
- default:
- return G_IO_ERROR_UNKNOWN;
- }
+ if (errno == EINVAL)
+ return G_IO_ERROR_INVAL;
+ else
+ return G_IO_ERROR_UNKNOWN;
}
else
{
@@ -544,18 +488,19 @@ g_io_win32_fd_read (GIOChannel *channel,
return G_IO_ERROR_NONE;
}
}
-
-static GIOError
-g_io_win32_fd_write(GIOChannel *channel,
- gchar *buf,
+
+static GIOError
+g_io_win32_fd_write(GIOChannel *channel,
+ gchar *buf,
guint count,
guint *bytes_written)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
gint result;
-
+
result = write (win32_channel->fd, buf, count);
-
+ PRINT (("g_io_win32_fd_write: fd:%d count:%d = %d\n", win32_channel->fd, count, result));
+
if (result < 0)
{
*bytes_written = 0;
@@ -576,15 +521,15 @@ g_io_win32_fd_write(GIOChannel *channel,
}
}
-static GIOError
+static GIOError
g_io_win32_fd_seek (GIOChannel *channel,
- gint offset,
+ gint offset,
GSeekType type)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
int whence;
off_t result;
-
+
switch (type)
{
case G_SEEK_SET:
@@ -617,16 +562,30 @@ g_io_win32_fd_seek (GIOChannel *channel,
return G_IO_ERROR_NONE;
}
-static void
+static void
g_io_win32_fd_close (GIOChannel *channel)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-
+
close (win32_channel->fd);
return;
}
-static guint
+static int
+fd_reader (int fd,
+ guchar *buf,
+ int len)
+{
+ int value;
+
+ value = read (fd, buf, len);
+
+ PRINT (("fd_reader (%d,%p,%d) = %d\n", fd, buf, len, value));
+
+ return value;
+}
+
+static guint
g_io_win32_fd_add_watch (GIOChannel *channel,
gint priority,
GIOCondition condition,
@@ -636,206 +595,65 @@ g_io_win32_fd_add_watch (GIOChannel *channel,
{
GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+ DWORD nbytes;
+ char dummy[1];
watch->channel = channel;
g_io_channel_ref (channel);
-
+
watch->callback = func;
watch->condition = condition;
+
+ create_events (win32_channel);
- /* This probably does not work, except for CONIN$. */
- watch->pollfd.fd = _get_osfhandle (win32_channel->fd);
+ watch->pollfd.fd = (gint) win32_channel->data_avail_event;
watch->pollfd.events = condition;
+
+ PRINT (("g_io_win32_fd_add_watch: fd:%d handle:%#x\n",
+ win32_channel->fd, watch->pollfd.fd));
+
+ /* Is it readable? (Would be strange to watch it otherwise, but... */
+ if (ReadFile ((HANDLE) _get_osfhandle (win32_channel->fd),
+ dummy, 0, &nbytes, NULL))
+ create_reader_thread (win32_channel, fd_reader);
g_main_add_poll (&watch->pollfd, priority);
-
- return g_source_add (priority, TRUE, &win32_watch_fd_funcs,
+
+ return g_source_add (priority, TRUE, &win32_watch_funcs,
watch, user_data, notify);
}
static GIOError
-g_io_win32_pipe_read (GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_read)
+g_io_win32_sock_read (GIOChannel *channel,
+ gchar *buf,
+ guint count,
+ guint *bytes_read)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
- HANDLE handle;
- DWORD avail;
gint result;
-
- handle = (HANDLE) _get_osfhandle (win32_channel->fd);
- if (!PeekNamedPipe (handle, NULL, 0, NULL, &avail, NULL))
- {
- return G_IO_ERROR_UNKNOWN;
- }
-
- count = MIN (count, avail);
-
- count = MAX (count, 1); /* Must read at least one byte, or
- * caller will think it's EOF.
- */
- /* g_print ("g_io_win32_pipe_read: %d %d\n", win32_channel->fd, count); */
- if (count == 0)
- result = 0;
- else
- result = read (win32_channel->fd, buf, count);
- if (result < 0)
+ GIOError error;
+
+ if (win32_channel->thread_id)
{
- *bytes_read = 0;
- switch (errno)
+ result = buffer_read (win32_channel, buf, count, &error);
+ if (result < 0)
{
- case EINVAL:
- return G_IO_ERROR_INVAL;
- case EAGAIN:
- return G_IO_ERROR_AGAIN;
- default:
- return G_IO_ERROR_UNKNOWN;
+ *bytes_read = 0;
+ return error;
}
- }
- else
- {
- *bytes_read = result;
- win32_channel->offset += result;
- /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
- return G_IO_ERROR_NONE;
- }
-}
-
-static GIOError
-g_io_win32_pipe_write(GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_written)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
- LONG prevcnt;
- gint result;
-
- /* g_print ("g_io_win32_pipe_write: %d %d\n", win32_channel->fd, count); */
- result = write (win32_channel->fd, buf, count);
- if (result < 0)
- {
- *bytes_written = 0;
- switch (errno)
+ else
{
- case EINVAL:
- return G_IO_ERROR_INVAL;
- case EAGAIN:
- return G_IO_ERROR_AGAIN;
- default:
- return G_IO_ERROR_UNKNOWN;
- }
- }
- else
- {
- if (g_pipe_readable_msg == 0)
- g_pipe_readable_msg = RegisterWindowMessage ("g-pipe-readable");
-
- win32_channel->offset += result;
- /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
- if (win32_channel->need_wakeups)
- {
- PostThreadMessage (win32_channel->peer,
- g_pipe_readable_msg,
- win32_channel->peer_fd,
- win32_channel->offset);
+ *bytes_read = result;
+ return G_IO_ERROR_NONE;
}
- *bytes_written = result;
- return G_IO_ERROR_NONE;
- }
-}
-
-static void
-g_io_win32_pipe_close (GIOChannel *channel)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-
- /* g_print ("g_io_win32_pipe_close: %#x %d\n", channel, win32_channel->fd); */
-
- close (win32_channel->fd);
- return;
-}
-
-static guint
-g_io_win32_pipe_add_watch (GIOChannel *channel,
- gint priority,
- GIOCondition condition,
- GIOFunc func,
- gpointer user_data,
- GDestroyNotify notify)
-{
- GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
- GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
- gint i;
-
- /* g_print ("g_io_win32_pipe_add_watch: %d\n", win32_channel->fd); */
-
- watch->channel = channel;
- g_io_channel_ref (channel);
-
- watch->callback = func;
- watch->condition = condition;
-
- watch->pollfd.fd = win32_channel->fd;
- watch->pollfd.events = condition;
-
- for (i = 0; i < n_watched_pipes; i++)
- if (watched_pipes[i].fd == -1)
- break;
- if (i == N_WATCHED_PIPES)
- g_error ("Too many watched pipes");
- else
- {
- watched_pipes[i].fd = win32_channel->fd;
- watched_pipes[i].watch = watch;
- watched_pipes[i].channel = win32_channel;
- watched_pipes[i].user_data = user_data;
- n_watched_pipes = MAX (i + 1, n_watched_pipes);
}
- return g_source_add (priority, FALSE, &win32_watch_pipe_funcs, watch, user_data, notify);
-}
-
-static void
-g_io_win32_pipe_free (GIOChannel *channel)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
- gint i;
-
- /* g_print ("g_io_win32_pipe_free: %#x %#x\n", channel, channel->channel_data); */
-
- for (i = 0; i < n_watched_pipes; i++)
- if (watched_pipes[i].fd == win32_channel->fd)
- {
- watched_pipes[i].fd = -1;
- break;
- }
- g_io_win32_free (channel);
-}
-
-static GIOError
-g_io_win32_sock_read (GIOChannel *channel,
- gchar *buf,
- guint count,
- guint *bytes_read)
-{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
- gint result;
result = recv (win32_channel->fd, buf, count, 0);
- if (result == SOCKET_ERROR)
+
+ if (result < 0)
{
*bytes_read = 0;
- switch (WSAGetLastError ())
- {
- case WSAEINVAL:
- return G_IO_ERROR_INVAL;
- case WSAEWOULDBLOCK:
- case WSAEINTR:
- return G_IO_ERROR_AGAIN;
- default:
- return G_IO_ERROR_UNKNOWN;
- }
+ return G_IO_ERROR_UNKNOWN;
}
else
{
@@ -843,18 +661,18 @@ g_io_win32_sock_read (GIOChannel *channel,
return G_IO_ERROR_NONE;
}
}
-
-static GIOError
-g_io_win32_sock_write(GIOChannel *channel,
- gchar *buf,
+
+static GIOError
+g_io_win32_sock_write(GIOChannel *channel,
+ gchar *buf,
guint count,
guint *bytes_written)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
gint result;
-
+
result = send (win32_channel->fd, buf, count, 0);
-
+
if (result == SOCKET_ERROR)
{
*bytes_written = 0;
@@ -876,16 +694,23 @@ g_io_win32_sock_write(GIOChannel *channel,
}
}
-static void
+static void
g_io_win32_sock_close (GIOChannel *channel)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
closesocket (win32_channel->fd);
- return;
}
-static guint
+static int
+sock_reader (int fd,
+ guchar *buf,
+ int len)
+{
+ return recv (fd, buf, len, 0);
+}
+
+static guint
g_io_win32_sock_add_watch (GIOChannel *channel,
gint priority,
GIOCondition condition,
@@ -895,21 +720,54 @@ g_io_win32_sock_add_watch (GIOChannel *channel,
{
GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-
+
watch->channel = channel;
g_io_channel_ref (channel);
watch->callback = func;
watch->condition = condition;
- watch->pollfd.fd = win32_channel->fd;
+ create_events (win32_channel);
+
+ watch->pollfd.fd = (gint) win32_channel->data_avail_event;
watch->pollfd.events = condition;
+ /* Sockets are always readable, aren't they? */
+ create_reader_thread (win32_channel, sock_reader);
+
g_main_add_poll (&watch->pollfd, priority);
- return g_source_add (priority, TRUE, &win32_watch_sock_funcs, watch, user_data, notify);
+ return g_source_add (priority, TRUE, &win32_watch_funcs, watch,
+ user_data, notify);
}
+static GIOFuncs win32_channel_msg_funcs = {
+ g_io_win32_msg_read,
+ g_io_win32_msg_write,
+ g_io_win32_no_seek,
+ g_io_win32_msg_close,
+ g_io_win32_msg_add_watch,
+ g_io_win32_free
+};
+
+static GIOFuncs win32_channel_fd_funcs = {
+ g_io_win32_fd_read,
+ g_io_win32_fd_write,
+ g_io_win32_fd_seek,
+ g_io_win32_fd_close,
+ g_io_win32_fd_add_watch,
+ g_io_win32_free
+};
+
+static GIOFuncs win32_channel_sock_funcs = {
+ g_io_win32_sock_read,
+ g_io_win32_sock_write,
+ g_io_win32_no_seek,
+ g_io_win32_sock_close,
+ g_io_win32_sock_add_watch,
+ g_io_win32_free
+};
+
GIOChannel *
g_io_channel_win32_new_messages (guint hwnd)
{
@@ -918,7 +776,6 @@ g_io_channel_win32_new_messages (guint hwnd)
g_io_channel_init (channel);
channel->funcs = &win32_channel_msg_funcs;
- win32_channel->fd = -1;
win32_channel->type = G_IO_WINDOWS_MESSAGES;
win32_channel->hwnd = (HWND) hwnd;
@@ -926,21 +783,37 @@ g_io_channel_win32_new_messages (guint hwnd)
}
GIOChannel *
-g_io_channel_unix_new (gint fd)
+g_io_channel_win32_new_fd (gint fd)
{
- GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
- GIOChannel *channel = (GIOChannel *) win32_channel;
+ GIOWin32Channel *win32_channel;
+ GIOChannel *channel;
+ struct stat st;
+
+ if (fstat (fd, &st) == -1)
+ {
+ g_warning ("%d isn't a (emulated) file descriptor", fd);
+ return NULL;
+ }
+
+ PRINT (("g_io_channel_win32_new_fd: %d\n", fd));
+
+ win32_channel = g_new (GIOWin32Channel, 1);
+ channel = (GIOChannel *) win32_channel;
g_io_channel_init (channel);
+
channel->funcs = &win32_channel_fd_funcs;
win32_channel->fd = fd;
win32_channel->type = G_IO_FILE_DESC;
+ win32_channel->buffer = NULL;
+ win32_channel->running = FALSE;
+ win32_channel->thread_id = 0;
return channel;
}
gint
-g_io_channel_unix_get_fd (GIOChannel *channel)
+g_io_channel_win32_get_fd (GIOChannel *channel)
{
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
@@ -948,88 +821,92 @@ g_io_channel_unix_get_fd (GIOChannel *channel)
}
GIOChannel *
-g_io_channel_win32_new_pipe_with_wakeups (int fd,
- guint peer,
- int peer_fd)
+g_io_channel_win32_new_stream_socket (int socket)
{
GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
GIOChannel *channel = (GIOChannel *) win32_channel;
- /* g_print ("g_io_channel_win32_new_pipe_with_wakeups %d %#x %d\n", fd, peer, peer_fd); */
-
g_io_channel_init (channel);
- channel->funcs = &win32_channel_pipe_funcs;
- win32_channel->fd = fd;
- win32_channel->type = G_IO_PIPE;
- win32_channel->peer = peer;
- win32_channel->peer_fd = peer_fd;
- win32_channel->offset = 0;
- win32_channel->need_wakeups = TRUE;
+ channel->funcs = &win32_channel_sock_funcs;
+ win32_channel->fd = socket;
+ win32_channel->type = G_IO_STREAM_SOCKET;
+ win32_channel->buffer = NULL;
+ win32_channel->running = FALSE;
+ win32_channel->thread_id = 0;
return channel;
}
GIOChannel *
-g_io_channel_win32_new_pipe (int fd)
+g_io_channel_unix_new (gint fd)
{
- GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
- GIOChannel *channel = (GIOChannel *) win32_channel;
-
- g_io_channel_init (channel);
- channel->funcs = &win32_channel_pipe_funcs;
- win32_channel->fd = fd;
- win32_channel->type = G_IO_PIPE;
- win32_channel->offset = 0;
- win32_channel->need_wakeups = FALSE;
+ return g_io_channel_win32_new_fd (fd);
+}
- return channel;
+gint
+g_io_channel_unix_get_fd (GIOChannel *channel)
+{
+ return g_io_channel_win32_get_fd (channel);
}
-GIOChannel *
-g_io_channel_win32_new_stream_socket (int socket)
+gint
+g_io_channel_win32_wait_for_condition (GIOChannel *channel,
+ GIOCondition condition,
+ gint timeout)
{
- GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
- GIOChannel *channel = (GIOChannel *) win32_channel;
+ GPollFD pollfd;
+ GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+ int result;
- g_io_channel_init (channel);
- channel->funcs = &win32_channel_sock_funcs;
- win32_channel->fd = socket;
- win32_channel->type = G_IO_STREAM_SOCKET;
+ pollfd.fd = (gint) win32_channel->data_avail_event;
+ pollfd.events = condition;
- return channel;
+ PRINT (("g_io_channel_win32_wait_for_condition: fd:%d event:%#x timeout:%d\n",
+ win32_channel->fd, pollfd.fd, timeout));
+
+ result = (*g_main_win32_get_poll_func ()) (&pollfd, 1, timeout);
+
+ PRINT (("g_io_channel_win32_wait_for_condition: done:%d\n", result));
+
+ return result;
}
-gint
-g_io_channel_win32_get_fd (GIOChannel *channel)
+
+/* This variable and the functions below are present just to be
+ * binary compatible with old clients... But note that in GIMP, the
+ * libgimp/gimp.c:gimp_extension_process() function will have to be modified
+ * anyhow for this new approach.
+ *
+ * These will be removed after some weeks.
+ */
+guint g_pipe_readable_msg = 0;
+
+GIOChannel *
+g_io_channel_win32_new_pipe (int fd)
+{
+ return g_io_channel_win32_new_fd (fd);
+}
+
+GIOChannel *
+g_io_channel_win32_new_pipe_with_wakeups (int fd,
+ guint peer,
+ int peer_fd)
{
- return g_io_channel_unix_get_fd (channel);
+ return g_io_channel_win32_new_fd (fd);
}
void
g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
- guint peer,
- int peer_fd)
+ guint peer,
+ int peer_fd)
{
- GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-
- win32_channel->peer = peer;
- win32_channel->peer_fd = peer_fd;
- win32_channel->need_wakeups = TRUE;
+ /* Nothing needed now */
}
void
g_io_channel_win32_pipe_readable (gint fd,
- guint offset)
+ guint offset)
{
- gint i;
-
- for (i = 0; i < n_watched_pipes; i++)
- if (watched_pipes[i].fd == fd)
- {
- if ((watched_pipes[i].watch->condition & G_IO_IN)
- && watched_pipes[i].channel->offset < offset)
- (*watched_pipes[i].watch->callback) (watched_pipes[i].watch->channel,
- G_IO_IN,
- watched_pipes[i].user_data);
- }
+ /* Nothing needed now */
}
+
diff --git a/glib/glib.def b/glib/glib.def
index e7fdb71a9..9e1b56ca1 100644
--- a/glib/glib.def
+++ b/glib/glib.def
@@ -160,11 +160,13 @@ EXPORTS
g_io_channel_unref
g_io_channel_win32_get_fd
g_io_channel_win32_new_messages
+ g_io_channel_win32_new_fd
g_io_channel_win32_new_pipe
g_io_channel_win32_new_pipe_with_wakeups
g_io_channel_win32_new_stream_socket
g_io_channel_win32_pipe_readable
g_io_channel_win32_pipe_request_wakeups
+ g_io_channel_win32_wait_for_condition
g_io_channel_write
g_list_alloc
g_list_append
@@ -207,6 +209,7 @@ EXPORTS
g_main_remove_poll
g_main_run
g_main_set_poll_func
+ g_main_win32_get_poll_func
g_malloc
g_malloc0
g_mem_check
diff --git a/glib/glib.h b/glib/glib.h
index 3100f5209..4ebe6626a 100644
--- a/glib/glib.h
+++ b/glib/glib.h
@@ -2881,29 +2881,43 @@ void g_main_add_poll (GPollFD *fd,
void g_main_remove_poll (GPollFD *fd);
void g_main_set_poll_func (GPollFunc func);
+#ifdef G_OS_WIN32
+
+/* Useful on other platforms, too? */
+
+GPollFunc g_main_win32_get_poll_func (void);
+
+#endif
+
/* On Unix, IO channels created with this function for any file
* descriptor or socket.
*
- * On Win32, use this only for plain files opened with the MSVCRT (the
- * Microsoft run-time C library) _open(), including file descriptors
- * 0, 1 and 2 (corresponding to stdin, stdout and stderr).
- * Actually, don't do even that, this code isn't done yet.
+ * On Win32, use this only for files opened with the MSVCRT (the
+ * Microsoft run-time C library) _open() or _pipe, including file
+ * descriptors 0, 1 and 2 (corresponding to stdin, stdout and stderr).
*
* The term file descriptor as used in the context of Win32 refers to
- * the emulated Unix-like file descriptors MSVCRT provides.
+ * the emulated Unix-like file descriptors MSVCRT provides. The native
+ * corresponding concept is file HANDLE. There isn't as of yet a way to
+ * get GIOChannels for file HANDLEs.
*/
GIOChannel* g_io_channel_unix_new (int fd);
gint g_io_channel_unix_get_fd (GIOChannel *channel);
#ifdef G_OS_WIN32
-GLIB_VAR guint g_pipe_readable_msg;
-
#define G_WIN32_MSG_HANDLE 19981206
+/* This can be used to wait until a channel is readable. On Unix you
+ * would do a select() on the fd of the channel. This should probably
+ * be replaced by something for all platforms?
+ */
+gint g_io_channel_win32_wait_for_condition (GIOChannel *channel,
+ GIOCondition condition,
+ gint timeout);
+
/* This is used to add polling for Windows messages. GDK (GTk+) programs
- * should *not* use this. (In fact, I can't think of any program that
- * would want to use this, but it's here just for completeness's sake.
+ * should *not* use this.
*/
void g_main_poll_win32_msg_add(gint priority,
GPollFD *fd,
@@ -2912,40 +2926,16 @@ void g_main_poll_win32_msg_add(gint priority,
/* An IO channel for Windows messages for window handle hwnd. */
GIOChannel *g_io_channel_win32_new_messages (guint hwnd);
-/* An IO channel for an anonymous pipe as returned from the MSVCRT
- * _pipe(), with no mechanism for the writer to tell the reader when
- * there is data in the pipe.
- *
- * This is not really implemented yet.
- */
-GIOChannel *g_io_channel_win32_new_pipe (int fd);
-
-/* An IO channel for a pipe as returned from the MSVCRT _pipe(), with
- * Windows user messages used to signal data in the pipe for the
- * reader.
- *
- * fd is the file descriptor. For the write end, peer is the thread id
- * of the reader, and peer_fd is his file descriptor for the read end
- * of the pipe.
- *
- * This is used by the GIMP, and works.
+/* An IO channel for C runtime (emulated Unix-like) file
+ * descriptors. Identical to g_io_channel_unix_new above.
*/
-GIOChannel *g_io_channel_win32_new_pipe_with_wakeups (int fd,
- guint peer,
- int peer_fd);
-
-void g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
- guint peer,
- int peer_fd);
-
-void g_io_channel_win32_pipe_readable (int fd,
- guint offset);
+GIOChannel* g_io_channel_win32_new_fd (int fd);
/* Get the C runtime file descriptor of a channel. */
gint g_io_channel_win32_get_fd (GIOChannel *channel);
-/* An IO channel for a SOCK_STREAM winsock socket. The parameter is
- * actually a SOCKET.
+/* An IO channel for a SOCK_STREAM winsock socket. The parameter should
+ * be a SOCKET.
*/
GIOChannel *g_io_channel_win32_new_stream_socket (int socket);
diff --git a/glib/gmain.c b/glib/gmain.c
index 23a0c30d2..a3404a6e9 100644
--- a/glib/gmain.c
+++ b/glib/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)