diff options
author | Marc-André Lureau <marcandre.lureau@gmail.com> | 2012-07-06 00:46:32 +0200 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@gmail.com> | 2012-08-20 17:10:31 +0200 |
commit | b9d7b80897d79cb43c4a795c7d9d3d9a24e140cc (patch) | |
tree | 95ddacd2e34d12a3c2efaa8cda3e2ca08af8bbb3 | |
parent | 4b5d762d5d73af90de49801ecc1da52d4cd86d6f (diff) | |
download | glib-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.c | 29 |
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 |