Bug 505361 - gunixinputstream.c assumes poll() available

Bug 509446 - portable blocking gio cancellation

	* gcancellable.c (g_cancellable_make_pollfd): New method to make a
	GPollFD for a cancellable (which is slightly more complicated on
	Windows than Unix).

	* gunixinputstream.c (g_unix_input_stream_read):
	* gunixoutputstream.c (g_unix_output_stream_write): Use
	g_cancellable_make_pollfd() and g_poll() rather than using poll()
	directly.

	* tests/unix-streams.c: test of GUnixInputStream,
	GUnixOutputStream, and GCancellable.

svn path=/trunk/; revision=7553
This commit is contained in:
Dan Winship
2008-09-26 16:19:35 +00:00
parent ea0970e9ca
commit 7f4864e58d
10 changed files with 356 additions and 29 deletions

View File

@@ -59,6 +59,10 @@ struct _GCancellable
guint cancelled : 1;
guint allocated_pipe : 1;
int cancel_pipe[2];
#ifdef G_OS_WIN32
GIOChannel *read_channel;
#endif
};
static guint signals[LAST_SIGNAL] = { 0 };
@@ -79,6 +83,11 @@ g_cancellable_finalize (GObject *object)
if (cancellable->cancel_pipe[1] != -1)
close (cancellable->cancel_pipe[1]);
#ifdef G_OS_WIN32
if (cancellable->read_channel)
g_io_channel_unref (cancellable->read_channel);
#endif
G_OBJECT_CLASS (g_cancellable_parent_class)->finalize (object);
}
@@ -304,6 +313,15 @@ g_cancellable_reset (GCancellable *cancellable)
if (cancellable->cancelled)
{
char ch;
#ifdef G_OS_WIN32
if (cancellable->read_channel)
{
gsize bytes_read;
g_io_channel_read_chars (cancellable->read_channel, &ch, 1,
&bytes_read, NULL);
}
else
#endif
if (cancellable->cancel_pipe[0] != -1)
read (cancellable->cancel_pipe[0], &ch, 1);
cancellable->cancelled = FALSE;
@@ -359,7 +377,9 @@ g_cancellable_set_error_if_cancelled (GCancellable *cancellable,
* Gets the file descriptor for a cancellable job. This can be used to
* implement cancellable operations on Unix systems. The returned fd will
* turn readable when @cancellable is cancelled.
*
*
* See also g_cancellable_make_pollfd().
*
* Returns: A valid file descriptor. %-1 if the file descriptor
* is not supported, or on errors.
**/
@@ -383,6 +403,41 @@ g_cancellable_get_fd (GCancellable *cancellable)
return fd;
}
/**
* g_cancellable_make_pollfd:
* @cancellable: a #GCancellable.
* @pollfd: a pointer to a #GPollFD
*
* Creates a #GPollFD corresponding to @cancellable; this can be passed
* to g_poll() and used to poll for cancellation.
**/
void
g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd)
{
g_return_if_fail (G_IS_CANCELLABLE (cancellable));
g_return_if_fail (pollfd != NULL);
#ifdef G_OS_WIN32
if (!cancellable->read_channel)
{
int fd = g_cancellable_get_fd (cancellable);
cancellable->read_channel = g_io_channel_win32_new_fd (fd);
g_io_channel_set_buffered (cancellable->read_channel, FALSE);
g_io_channel_set_flags (cancellable->read_channel,
G_IO_FLAG_NONBLOCK, NULL);
g_io_channel_set_encoding (cancellable->read_channel, NULL, NULL);
}
g_io_channel_win32_make_pollfd (cancellable->read_channel, G_IO_IN, pollfd);
/* (We need to keep cancellable->read_channel around, because it's
* keeping track of state related to the pollfd.)
*/
#else /* !G_OS_WIN32 */
pollfd->fd = g_cancellable_get_fd (cancellable);
pollfd->events = G_IO_IN;
#endif /* G_OS_WIN32 */
pollfd->revents = 0;
}
/**
* g_cancellable_cancel:
* @cancellable: a #GCancellable object.