[glib] win32: make gio stream cancellable



commit b9d7b80897d79cb43c4a795c7d9d3d9a24e140cc
Author: Marc-Andrà Lureau <marcandre lureau gmail com>
Date:   Fri Jul 6 00:46:32 2012 +0200

    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

 gio/gasynchelper.c |   29 +++++++++++++++++++++++++----
 1 files changed, 25 insertions(+), 4 deletions(-)
---
diff --git a/gio/gasynchelper.c b/gio/gasynchelper.c
index fa6c816..ab8bd2c 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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]