d-pointerize QWinOverlappedIoNotifier
Preparation for removing the qt_windows.h include from qwinoverlappedionotifier_p.h. Change-Id: I27ab3891962327ab5db75fbfcc3cf57c50a0d1c4 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com> Reviewed-by: Laszlo Papp <lpapp@kde.org>
This commit is contained in:
parent
adcab02d96
commit
d19eef3bbb
@ -43,8 +43,10 @@
|
|||||||
#include <qdebug.h>
|
#include <qdebug.h>
|
||||||
#include <qmutex.h>
|
#include <qmutex.h>
|
||||||
#include <qpointer.h>
|
#include <qpointer.h>
|
||||||
|
#include <qqueue.h>
|
||||||
#include <qset.h>
|
#include <qset.h>
|
||||||
#include <qthread.h>
|
#include <qthread.h>
|
||||||
|
#include <private/qobject_p.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -79,6 +81,46 @@ QT_BEGIN_NAMESPACE
|
|||||||
\warning This class is only available on Windows.
|
\warning This class is only available on Windows.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct IOResult
|
||||||
|
{
|
||||||
|
IOResult(DWORD n = 0, DWORD e = 0, OVERLAPPED *p = 0)
|
||||||
|
: numberOfBytes(n), errorCode(e), overlapped(p)
|
||||||
|
{}
|
||||||
|
|
||||||
|
DWORD numberOfBytes;
|
||||||
|
DWORD errorCode;
|
||||||
|
OVERLAPPED *overlapped;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class QWinIoCompletionPort;
|
||||||
|
|
||||||
|
class QWinOverlappedIoNotifierPrivate : public QObjectPrivate
|
||||||
|
{
|
||||||
|
Q_DECLARE_PUBLIC(QWinOverlappedIoNotifier)
|
||||||
|
public:
|
||||||
|
QWinOverlappedIoNotifierPrivate()
|
||||||
|
: hHandle(INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped);
|
||||||
|
OVERLAPPED *_q_notified();
|
||||||
|
|
||||||
|
static QWinIoCompletionPort *iocp;
|
||||||
|
static HANDLE iocpInstanceLock;
|
||||||
|
static unsigned int iocpInstanceRefCount;
|
||||||
|
HANDLE hHandle;
|
||||||
|
HANDLE hSemaphore;
|
||||||
|
HANDLE hResultsMutex;
|
||||||
|
QQueue<IOResult> results;
|
||||||
|
};
|
||||||
|
|
||||||
|
QWinIoCompletionPort *QWinOverlappedIoNotifierPrivate::iocp = 0;
|
||||||
|
HANDLE QWinOverlappedIoNotifierPrivate::iocpInstanceLock = CreateMutex(NULL, FALSE, NULL);
|
||||||
|
unsigned int QWinOverlappedIoNotifierPrivate::iocpInstanceRefCount = 0;
|
||||||
|
|
||||||
|
|
||||||
class QWinIoCompletionPort : protected QThread
|
class QWinIoCompletionPort : protected QThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -109,11 +151,13 @@ public:
|
|||||||
CloseHandle(hQueueDrainedEvent);
|
CloseHandle(hQueueDrainedEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerNotifier(QWinOverlappedIoNotifier *notifier)
|
void registerNotifier(QWinOverlappedIoNotifierPrivate *notifier)
|
||||||
{
|
{
|
||||||
HANDLE hIOCP = CreateIoCompletionPort(notifier->hHandle, hPort, reinterpret_cast<ULONG_PTR>(notifier), 0);
|
const HANDLE hHandle = notifier->hHandle;
|
||||||
|
HANDLE hIOCP = CreateIoCompletionPort(hHandle, hPort,
|
||||||
|
reinterpret_cast<ULONG_PTR>(notifier), 0);
|
||||||
if (!hIOCP) {
|
if (!hIOCP) {
|
||||||
qErrnoWarning("Can't associate file handle %x with I/O completion port.", notifier->hHandle);
|
qErrnoWarning("Can't associate file handle %x with I/O completion port.", hHandle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
@ -123,7 +167,7 @@ public:
|
|||||||
QThread::start();
|
QThread::start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void unregisterNotifier(QWinOverlappedIoNotifier *notifier)
|
void unregisterNotifier(QWinOverlappedIoNotifierPrivate *notifier)
|
||||||
{
|
{
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
notifiers.remove(notifier);
|
notifiers.remove(notifier);
|
||||||
@ -176,7 +220,8 @@ protected:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWinOverlappedIoNotifier *notifier = reinterpret_cast<QWinOverlappedIoNotifier *>(pulCompletionKey);
|
QWinOverlappedIoNotifierPrivate *notifier
|
||||||
|
= reinterpret_cast<QWinOverlappedIoNotifierPrivate *>(pulCompletionKey);
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
if (notifiers.contains(notifier))
|
if (notifiers.contains(notifier))
|
||||||
notifier->notify(dwBytesRead, errorCode, overlapped);
|
notifier->notify(dwBytesRead, errorCode, overlapped);
|
||||||
@ -188,57 +233,62 @@ private:
|
|||||||
const ULONG_PTR finishThreadKey;
|
const ULONG_PTR finishThreadKey;
|
||||||
const ULONG_PTR drainQueueKey;
|
const ULONG_PTR drainQueueKey;
|
||||||
HANDLE hPort;
|
HANDLE hPort;
|
||||||
QSet<QWinOverlappedIoNotifier *> notifiers;
|
QSet<QWinOverlappedIoNotifierPrivate *> notifiers;
|
||||||
QMutex mutex;
|
QMutex mutex;
|
||||||
QMutex drainQueueMutex;
|
QMutex drainQueueMutex;
|
||||||
HANDLE hQueueDrainedEvent;
|
HANDLE hQueueDrainedEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
QWinIoCompletionPort *QWinOverlappedIoNotifier::iocp = 0;
|
|
||||||
HANDLE QWinOverlappedIoNotifier::iocpInstanceLock = CreateMutex(NULL, FALSE, NULL);
|
|
||||||
unsigned int QWinOverlappedIoNotifier::iocpInstanceRefCount = 0;
|
|
||||||
|
|
||||||
QWinOverlappedIoNotifier::QWinOverlappedIoNotifier(QObject *parent)
|
QWinOverlappedIoNotifier::QWinOverlappedIoNotifier(QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(*new QWinOverlappedIoNotifierPrivate, parent)
|
||||||
hHandle(INVALID_HANDLE_VALUE)
|
|
||||||
{
|
{
|
||||||
WaitForSingleObject(iocpInstanceLock, INFINITE);
|
Q_D(QWinOverlappedIoNotifier);
|
||||||
if (!iocp)
|
WaitForSingleObject(d->iocpInstanceLock, INFINITE);
|
||||||
iocp = new QWinIoCompletionPort;
|
if (!d->iocp)
|
||||||
iocpInstanceRefCount++;
|
d->iocp = new QWinIoCompletionPort;
|
||||||
ReleaseMutex(iocpInstanceLock);
|
d->iocpInstanceRefCount++;
|
||||||
|
ReleaseMutex(d->iocpInstanceLock);
|
||||||
|
|
||||||
hSemaphore = CreateSemaphore(NULL, 0, 255, NULL);
|
d->hSemaphore = CreateSemaphore(NULL, 0, 255, NULL);
|
||||||
hResultsMutex = CreateMutex(NULL, FALSE, NULL);
|
d->hResultsMutex = CreateMutex(NULL, FALSE, NULL);
|
||||||
connect(this, &QWinOverlappedIoNotifier::_q_notify,
|
connect(this, SIGNAL(_q_notify()), this, SLOT(_q_notified()), Qt::QueuedConnection);
|
||||||
this, &QWinOverlappedIoNotifier::_q_notified, Qt::QueuedConnection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QWinOverlappedIoNotifier::~QWinOverlappedIoNotifier()
|
QWinOverlappedIoNotifier::~QWinOverlappedIoNotifier()
|
||||||
{
|
{
|
||||||
|
Q_D(QWinOverlappedIoNotifier);
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
CloseHandle(hResultsMutex);
|
CloseHandle(d->hResultsMutex);
|
||||||
CloseHandle(hSemaphore);
|
CloseHandle(d->hSemaphore);
|
||||||
|
|
||||||
WaitForSingleObject(iocpInstanceLock, INFINITE);
|
WaitForSingleObject(d->iocpInstanceLock, INFINITE);
|
||||||
if (!--iocpInstanceRefCount) {
|
if (!--d->iocpInstanceRefCount) {
|
||||||
delete iocp;
|
delete d->iocp;
|
||||||
iocp = 0;
|
d->iocp = 0;
|
||||||
}
|
}
|
||||||
ReleaseMutex(iocpInstanceLock);
|
ReleaseMutex(d->iocpInstanceLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWinOverlappedIoNotifier::setHandle(HANDLE h)
|
void QWinOverlappedIoNotifier::setHandle(HANDLE h)
|
||||||
{
|
{
|
||||||
hHandle = h;
|
Q_D(QWinOverlappedIoNotifier);
|
||||||
|
d->hHandle = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE QWinOverlappedIoNotifier::handle() const
|
||||||
|
{
|
||||||
|
Q_D(const QWinOverlappedIoNotifier);
|
||||||
|
return d->hHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWinOverlappedIoNotifier::setEnabled(bool enabled)
|
void QWinOverlappedIoNotifier::setEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
|
Q_D(QWinOverlappedIoNotifier);
|
||||||
if (enabled)
|
if (enabled)
|
||||||
iocp->registerNotifier(this);
|
d->iocp->registerNotifier(d);
|
||||||
else
|
else
|
||||||
iocp->unregisterNotifier(this);
|
d->iocp->unregisterNotifier(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -249,18 +299,19 @@ void QWinOverlappedIoNotifier::setEnabled(bool enabled)
|
|||||||
*/
|
*/
|
||||||
bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped)
|
bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped)
|
||||||
{
|
{
|
||||||
if (!iocp->isRunning()) {
|
Q_D(QWinOverlappedIoNotifier);
|
||||||
|
if (!d->iocp->isRunning()) {
|
||||||
qWarning("Called QWinOverlappedIoNotifier::waitForNotified on inactive notifier.");
|
qWarning("Called QWinOverlappedIoNotifier::waitForNotified on inactive notifier.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
forever {
|
forever {
|
||||||
if (msecs == 0)
|
if (msecs == 0)
|
||||||
iocp->drainQueue();
|
d->iocp->drainQueue();
|
||||||
DWORD result = WaitForSingleObject(hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs));
|
DWORD result = WaitForSingleObject(d->hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs));
|
||||||
if (result == WAIT_OBJECT_0) {
|
if (result == WAIT_OBJECT_0) {
|
||||||
ReleaseSemaphore(hSemaphore, 1, NULL);
|
ReleaseSemaphore(d->hSemaphore, 1, NULL);
|
||||||
if (_q_notified() == overlapped)
|
if (d->_q_notified() == overlapped)
|
||||||
return true;
|
return true;
|
||||||
continue;
|
continue;
|
||||||
} else if (result == WAIT_TIMEOUT) {
|
} else if (result == WAIT_TIMEOUT) {
|
||||||
@ -275,25 +326,30 @@ bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped
|
|||||||
/*!
|
/*!
|
||||||
* Note: This function runs in the I/O completion port thread.
|
* Note: This function runs in the I/O completion port thread.
|
||||||
*/
|
*/
|
||||||
void QWinOverlappedIoNotifier::notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped)
|
void QWinOverlappedIoNotifierPrivate::notify(DWORD numberOfBytes, DWORD errorCode,
|
||||||
|
OVERLAPPED *overlapped)
|
||||||
{
|
{
|
||||||
|
Q_Q(QWinOverlappedIoNotifier);
|
||||||
WaitForSingleObject(hResultsMutex, INFINITE);
|
WaitForSingleObject(hResultsMutex, INFINITE);
|
||||||
results.enqueue(IOResult(numberOfBytes, errorCode, overlapped));
|
results.enqueue(IOResult(numberOfBytes, errorCode, overlapped));
|
||||||
ReleaseMutex(hResultsMutex);
|
ReleaseMutex(hResultsMutex);
|
||||||
ReleaseSemaphore(hSemaphore, 1, NULL);
|
ReleaseSemaphore(hSemaphore, 1, NULL);
|
||||||
emit _q_notify();
|
emit q->_q_notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
OVERLAPPED *QWinOverlappedIoNotifier::_q_notified()
|
OVERLAPPED *QWinOverlappedIoNotifierPrivate::_q_notified()
|
||||||
{
|
{
|
||||||
|
Q_Q(QWinOverlappedIoNotifier);
|
||||||
if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0) {
|
if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0) {
|
||||||
WaitForSingleObject(hResultsMutex, INFINITE);
|
WaitForSingleObject(hResultsMutex, INFINITE);
|
||||||
IOResult ioresult = results.dequeue();
|
IOResult ioresult = results.dequeue();
|
||||||
ReleaseMutex(hResultsMutex);
|
ReleaseMutex(hResultsMutex);
|
||||||
emit notified(ioresult.numberOfBytes, ioresult.errorCode, ioresult.overlapped);
|
emit q->notified(ioresult.numberOfBytes, ioresult.errorCode, ioresult.overlapped);
|
||||||
return ioresult.overlapped;
|
return ioresult.overlapped;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#include "moc_qwinoverlappedionotifier_p.cpp"
|
||||||
|
@ -55,57 +55,33 @@
|
|||||||
|
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
#include <qt_windows.h>
|
#include <qt_windows.h>
|
||||||
#include <qqueue.h>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QWinIoCompletionPort;
|
class QWinOverlappedIoNotifierPrivate;
|
||||||
|
|
||||||
class Q_CORE_EXPORT QWinOverlappedIoNotifier : public QObject
|
class Q_CORE_EXPORT QWinOverlappedIoNotifier : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY(QWinOverlappedIoNotifier)
|
||||||
|
Q_DECLARE_PRIVATE(QWinOverlappedIoNotifier)
|
||||||
|
Q_PRIVATE_SLOT(d_func(), OVERLAPPED *_q_notified())
|
||||||
|
friend class QWinIoCompletionPort;
|
||||||
public:
|
public:
|
||||||
QWinOverlappedIoNotifier(QObject *parent = 0);
|
QWinOverlappedIoNotifier(QObject *parent = 0);
|
||||||
~QWinOverlappedIoNotifier();
|
~QWinOverlappedIoNotifier();
|
||||||
|
|
||||||
void setHandle(HANDLE h);
|
void setHandle(HANDLE h);
|
||||||
HANDLE handle() const { return hHandle; }
|
HANDLE handle() const;
|
||||||
|
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
bool waitForNotified(int msecs, OVERLAPPED *overlapped);
|
bool waitForNotified(int msecs, OVERLAPPED *overlapped);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void notified(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped);
|
void notified(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped);
|
||||||
|
#if !defined(Q_QDOC)
|
||||||
void _q_notify();
|
void _q_notify();
|
||||||
|
#endif
|
||||||
private Q_SLOTS:
|
|
||||||
OVERLAPPED *_q_notified();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static QWinIoCompletionPort *iocp;
|
|
||||||
static HANDLE iocpInstanceLock;
|
|
||||||
static unsigned int iocpInstanceRefCount;
|
|
||||||
HANDLE hHandle;
|
|
||||||
HANDLE hSemaphore;
|
|
||||||
HANDLE hResultsMutex;
|
|
||||||
|
|
||||||
struct IOResult
|
|
||||||
{
|
|
||||||
IOResult(DWORD n = 0, DWORD e = 0, OVERLAPPED *p = 0)
|
|
||||||
: numberOfBytes(n), errorCode(e), overlapped(p)
|
|
||||||
{}
|
|
||||||
|
|
||||||
DWORD numberOfBytes;
|
|
||||||
DWORD errorCode;
|
|
||||||
OVERLAPPED *overlapped;
|
|
||||||
};
|
|
||||||
|
|
||||||
QQueue<IOResult> results;
|
|
||||||
|
|
||||||
friend class QWinIoCompletionPort;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
Loading…
Reference in New Issue
Block a user