summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qwinoverlappedionotifier.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io/qwinoverlappedionotifier.cpp')
-rw-r--r--src/corelib/io/qwinoverlappedionotifier.cpp61
1 files changed, 38 insertions, 23 deletions
diff --git a/src/corelib/io/qwinoverlappedionotifier.cpp b/src/corelib/io/qwinoverlappedionotifier.cpp
index 0c698c6e53..c084912897 100644
--- a/src/corelib/io/qwinoverlappedionotifier.cpp
+++ b/src/corelib/io/qwinoverlappedionotifier.cpp
@@ -62,7 +62,8 @@ QT_BEGIN_NAMESPACE
Once you have obtained a file handle, you can use setHandle() to get
notifications for I/O operations. Whenever an I/O operation completes,
the notified() signal is emitted which will pass the number of transferred
- bytes and the operation's error code to the receiver.
+ bytes, the operation's error code and a pointer to the operation's
+ OVERLAPPED object to the receiver.
Every handle that supports overlapped I/O can be used by
QWinOverlappedIoNotifier. That includes file handles, TCP sockets
@@ -149,7 +150,7 @@ protected:
QWinOverlappedIoNotifier *notifier = reinterpret_cast<QWinOverlappedIoNotifier *>(pulCompletionKey);
mutex.lock();
if (notifiers.contains(notifier))
- notifier->notify(dwBytesRead, errorCode);
+ notifier->notify(dwBytesRead, errorCode, overlapped);
mutex.unlock();
}
}
@@ -164,11 +165,10 @@ Q_GLOBAL_STATIC(QWinIoCompletionPort, iocp)
QWinOverlappedIoNotifier::QWinOverlappedIoNotifier(QObject *parent)
: QObject(parent),
- hHandle(INVALID_HANDLE_VALUE),
- lastNumberOfBytes(0),
- lastErrorCode(ERROR_SUCCESS)
+ hHandle(INVALID_HANDLE_VALUE)
{
- hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ hSemaphore = CreateSemaphore(NULL, 0, 255, NULL);
+ hResultsMutex = CreateMutex(NULL, FALSE, NULL);
connect(this, &QWinOverlappedIoNotifier::_q_notify,
this, &QWinOverlappedIoNotifier::_q_notified, Qt::QueuedConnection);
}
@@ -176,7 +176,8 @@ QWinOverlappedIoNotifier::QWinOverlappedIoNotifier(QObject *parent)
QWinOverlappedIoNotifier::~QWinOverlappedIoNotifier()
{
setEnabled(false);
- CloseHandle(hEvent);
+ CloseHandle(hResultsMutex);
+ CloseHandle(hSemaphore);
}
void QWinOverlappedIoNotifier::setHandle(HANDLE h)
@@ -192,15 +193,24 @@ void QWinOverlappedIoNotifier::setEnabled(bool enabled)
iocp()->unregisterNotifier(this);
}
-bool QWinOverlappedIoNotifier::waitForNotified(int msecs)
+/*!
+ * Wait synchronously for the notified signal.
+ *
+ * \returns true, if the notified signal was emitted for the I/O operation
+ * that corresponds to the OVERLAPPED object.
+ */
+bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped)
{
- DWORD result = WaitForSingleObject(hEvent, msecs == -1 ? INFINITE : DWORD(msecs));
- switch (result) {
- case WAIT_OBJECT_0:
- _q_notified();
- return true;
- case WAIT_TIMEOUT:
- return false;
+ forever {
+ DWORD result = WaitForSingleObject(hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs));
+ if (result == WAIT_OBJECT_0) {
+ ReleaseSemaphore(hSemaphore, 1, NULL);
+ if (_q_notified() == overlapped)
+ return true;
+ continue;
+ } else if (result == WAIT_TIMEOUT) {
+ return false;
+ }
}
qErrnoWarning("QWinOverlappedIoNotifier::waitForNotified: WaitForSingleObject failed.");
@@ -210,20 +220,25 @@ bool QWinOverlappedIoNotifier::waitForNotified(int msecs)
/*!
* Note: This function runs in the I/O completion port thread.
*/
-void QWinOverlappedIoNotifier::notify(DWORD numberOfBytes, DWORD errorCode)
+void QWinOverlappedIoNotifier::notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped)
{
- lastNumberOfBytes = numberOfBytes;
- lastErrorCode = errorCode;
- SetEvent(hEvent);
+ WaitForSingleObject(hResultsMutex, INFINITE);
+ results.enqueue(IOResult(numberOfBytes, errorCode, overlapped));
+ ReleaseMutex(hResultsMutex);
+ ReleaseSemaphore(hSemaphore, 1, NULL);
emit _q_notify();
}
-void QWinOverlappedIoNotifier::_q_notified()
+OVERLAPPED *QWinOverlappedIoNotifier::_q_notified()
{
- if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) {
- ResetEvent(hEvent);
- emit notified(lastNumberOfBytes, lastErrorCode);
+ if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0) {
+ WaitForSingleObject(hResultsMutex, INFINITE);
+ IOResult ioresult = results.dequeue();
+ ReleaseMutex(hResultsMutex);
+ emit notified(ioresult.numberOfBytes, ioresult.errorCode, ioresult.overlapped);
+ return ioresult.overlapped;
}
+ return 0;
}
QT_END_NAMESPACE