summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@gmail.com>2012-07-06 00:46:32 +0200
committerMarc-André Lureau <marcandre.lureau@gmail.com>2012-08-20 17:10:31 +0200
commitb9d7b80897d79cb43c4a795c7d9d3d9a24e140cc (patch)
tree95ddacd2e34d12a3c2efaa8cda3e2ca08af8bbb3
parent4b5d762d5d73af90de49801ecc1da52d4cd86d6f (diff)
downloadglib-b9d7b80897d79cb43c4a795c7d9d3d9a24e140cc.tar.gz
win32: make gio stream cancellable
v2: - fix cancellation of concurrent readers - replace g_assert() usage with g_warn_if_fail() v3: - fix indentation - fix loop code to not leak (silly me) https://bugzilla.gnome.org/show_bug.cgi?id=679288
-rw-r--r--gio/gasynchelper.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/gio/gasynchelper.c b/gio/gasynchelper.c
index fa6c8162b..ab8bd2c1d 100644
--- a/gio/gasynchelper.c
+++ b/gio/gasynchelper.c
@@ -174,9 +174,9 @@ gboolean
_g_win32_overlap_wait_result (HANDLE hfile,
OVERLAPPED *overlap,
DWORD *transferred,
- GCancellable *cancellable G_GNUC_UNUSED)
+ GCancellable *cancellable)
{
- GPollFD pollfd[1] = { 0, };
+ GPollFD pollfd[2];
gboolean result = FALSE;
gint num, npoll;
@@ -184,15 +184,36 @@ _g_win32_overlap_wait_result (HANDLE hfile,
pollfd[0].events = G_IO_IN;
num = 1;
+ if (g_cancellable_make_pollfd (cancellable, &pollfd[1]))
+ num++;
+
+loop:
npoll = g_poll (pollfd, num, -1);
if (npoll <= 0)
/* error out, should never happen */
goto end;
- /* either cancelled or IO completed, either way get the result */
- result = GetOverlappedResult (overlap->hEvent, overlap, transferred, TRUE);
+ if (g_cancellable_is_cancelled (cancellable))
+ {
+ /* CancelIO only cancels pending operations issued by the
+ * current thread and since we're doing only sync operations,
+ * this is safe.... */
+ /* CancelIoEx is only Vista+. Since we have only one overlap
+ * operaton on this thread, we can just use: */
+ result = CancelIo (hfile);
+ g_warn_if_fail (result);
+ }
+
+ result = GetOverlappedResult (overlap->hEvent, overlap, transferred, FALSE);
+ if (result == FALSE &&
+ GetLastError () == ERROR_IO_INCOMPLETE &&
+ !g_cancellable_is_cancelled (cancellable))
+ goto loop;
end:
+ if (num > 1)
+ g_cancellable_release_fd (cancellable);
+
return result;
}
#endif