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 <qmutex.h>
|
||||
#include <qpointer.h>
|
||||
#include <qqueue.h>
|
||||
#include <qset.h>
|
||||
#include <qthread.h>
|
||||
#include <private/qobject_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -79,6 +81,46 @@ QT_BEGIN_NAMESPACE
|
||||
\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
|
||||
{
|
||||
public:
|
||||
@ -109,11 +151,13 @@ public:
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
mutex.lock();
|
||||
@ -123,7 +167,7 @@ public:
|
||||
QThread::start();
|
||||
}
|
||||
|
||||
void unregisterNotifier(QWinOverlappedIoNotifier *notifier)
|
||||
void unregisterNotifier(QWinOverlappedIoNotifierPrivate *notifier)
|
||||
{
|
||||
mutex.lock();
|
||||
notifiers.remove(notifier);
|
||||
@ -176,7 +220,8 @@ protected:
|
||||
continue;
|
||||
}
|
||||
|
||||
QWinOverlappedIoNotifier *notifier = reinterpret_cast<QWinOverlappedIoNotifier *>(pulCompletionKey);
|
||||
QWinOverlappedIoNotifierPrivate *notifier
|
||||
= reinterpret_cast<QWinOverlappedIoNotifierPrivate *>(pulCompletionKey);
|
||||
mutex.lock();
|
||||
if (notifiers.contains(notifier))
|
||||
notifier->notify(dwBytesRead, errorCode, overlapped);
|
||||
@ -188,57 +233,62 @@ private:
|
||||
const ULONG_PTR finishThreadKey;
|
||||
const ULONG_PTR drainQueueKey;
|
||||
HANDLE hPort;
|
||||
QSet<QWinOverlappedIoNotifier *> notifiers;
|
||||
QSet<QWinOverlappedIoNotifierPrivate *> notifiers;
|
||||
QMutex mutex;
|
||||
QMutex drainQueueMutex;
|
||||
HANDLE hQueueDrainedEvent;
|
||||
};
|
||||
|
||||
QWinIoCompletionPort *QWinOverlappedIoNotifier::iocp = 0;
|
||||
HANDLE QWinOverlappedIoNotifier::iocpInstanceLock = CreateMutex(NULL, FALSE, NULL);
|
||||
unsigned int QWinOverlappedIoNotifier::iocpInstanceRefCount = 0;
|
||||
|
||||
QWinOverlappedIoNotifier::QWinOverlappedIoNotifier(QObject *parent)
|
||||
: QObject(parent),
|
||||
hHandle(INVALID_HANDLE_VALUE)
|
||||
: QObject(*new QWinOverlappedIoNotifierPrivate, parent)
|
||||
{
|
||||
WaitForSingleObject(iocpInstanceLock, INFINITE);
|
||||
if (!iocp)
|
||||
iocp = new QWinIoCompletionPort;
|
||||
iocpInstanceRefCount++;
|
||||
ReleaseMutex(iocpInstanceLock);
|
||||
Q_D(QWinOverlappedIoNotifier);
|
||||
WaitForSingleObject(d->iocpInstanceLock, INFINITE);
|
||||
if (!d->iocp)
|
||||
d->iocp = new QWinIoCompletionPort;
|
||||
d->iocpInstanceRefCount++;
|
||||
ReleaseMutex(d->iocpInstanceLock);
|
||||
|
||||
hSemaphore = CreateSemaphore(NULL, 0, 255, NULL);
|
||||
hResultsMutex = CreateMutex(NULL, FALSE, NULL);
|
||||
connect(this, &QWinOverlappedIoNotifier::_q_notify,
|
||||
this, &QWinOverlappedIoNotifier::_q_notified, Qt::QueuedConnection);
|
||||
d->hSemaphore = CreateSemaphore(NULL, 0, 255, NULL);
|
||||
d->hResultsMutex = CreateMutex(NULL, FALSE, NULL);
|
||||
connect(this, SIGNAL(_q_notify()), this, SLOT(_q_notified()), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
QWinOverlappedIoNotifier::~QWinOverlappedIoNotifier()
|
||||
{
|
||||
Q_D(QWinOverlappedIoNotifier);
|
||||
setEnabled(false);
|
||||
CloseHandle(hResultsMutex);
|
||||
CloseHandle(hSemaphore);
|
||||
CloseHandle(d->hResultsMutex);
|
||||
CloseHandle(d->hSemaphore);
|
||||
|
||||
WaitForSingleObject(iocpInstanceLock, INFINITE);
|
||||
if (!--iocpInstanceRefCount) {
|
||||
delete iocp;
|
||||
iocp = 0;
|
||||
WaitForSingleObject(d->iocpInstanceLock, INFINITE);
|
||||
if (!--d->iocpInstanceRefCount) {
|
||||
delete d->iocp;
|
||||
d->iocp = 0;
|
||||
}
|
||||
ReleaseMutex(iocpInstanceLock);
|
||||
ReleaseMutex(d->iocpInstanceLock);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Q_D(QWinOverlappedIoNotifier);
|
||||
if (enabled)
|
||||
iocp->registerNotifier(this);
|
||||
d->iocp->registerNotifier(d);
|
||||
else
|
||||
iocp->unregisterNotifier(this);
|
||||
d->iocp->unregisterNotifier(d);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -249,18 +299,19 @@ void QWinOverlappedIoNotifier::setEnabled(bool enabled)
|
||||
*/
|
||||
bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped)
|
||||
{
|
||||
if (!iocp->isRunning()) {
|
||||
Q_D(QWinOverlappedIoNotifier);
|
||||
if (!d->iocp->isRunning()) {
|
||||
qWarning("Called QWinOverlappedIoNotifier::waitForNotified on inactive notifier.");
|
||||
return false;
|
||||
}
|
||||
|
||||
forever {
|
||||
if (msecs == 0)
|
||||
iocp->drainQueue();
|
||||
DWORD result = WaitForSingleObject(hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs));
|
||||
d->iocp->drainQueue();
|
||||
DWORD result = WaitForSingleObject(d->hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs));
|
||||
if (result == WAIT_OBJECT_0) {
|
||||
ReleaseSemaphore(hSemaphore, 1, NULL);
|
||||
if (_q_notified() == overlapped)
|
||||
ReleaseSemaphore(d->hSemaphore, 1, NULL);
|
||||
if (d->_q_notified() == overlapped)
|
||||
return true;
|
||||
continue;
|
||||
} 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.
|
||||
*/
|
||||
void QWinOverlappedIoNotifier::notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped)
|
||||
void QWinOverlappedIoNotifierPrivate::notify(DWORD numberOfBytes, DWORD errorCode,
|
||||
OVERLAPPED *overlapped)
|
||||
{
|
||||
Q_Q(QWinOverlappedIoNotifier);
|
||||
WaitForSingleObject(hResultsMutex, INFINITE);
|
||||
results.enqueue(IOResult(numberOfBytes, errorCode, overlapped));
|
||||
ReleaseMutex(hResultsMutex);
|
||||
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) {
|
||||
WaitForSingleObject(hResultsMutex, INFINITE);
|
||||
IOResult ioresult = results.dequeue();
|
||||
ReleaseMutex(hResultsMutex);
|
||||
emit notified(ioresult.numberOfBytes, ioresult.errorCode, ioresult.overlapped);
|
||||
emit q->notified(ioresult.numberOfBytes, ioresult.errorCode, ioresult.overlapped);
|
||||
return ioresult.overlapped;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "moc_qwinoverlappedionotifier_p.cpp"
|
||||
|
@ -55,57 +55,33 @@
|
||||
|
||||
#include <qobject.h>
|
||||
#include <qt_windows.h>
|
||||
#include <qqueue.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QWinIoCompletionPort;
|
||||
class QWinOverlappedIoNotifierPrivate;
|
||||
|
||||
class Q_CORE_EXPORT QWinOverlappedIoNotifier : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(QWinOverlappedIoNotifier)
|
||||
Q_DECLARE_PRIVATE(QWinOverlappedIoNotifier)
|
||||
Q_PRIVATE_SLOT(d_func(), OVERLAPPED *_q_notified())
|
||||
friend class QWinIoCompletionPort;
|
||||
public:
|
||||
QWinOverlappedIoNotifier(QObject *parent = 0);
|
||||
~QWinOverlappedIoNotifier();
|
||||
|
||||
void setHandle(HANDLE h);
|
||||
HANDLE handle() const { return hHandle; }
|
||||
HANDLE handle() const;
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
bool waitForNotified(int msecs, OVERLAPPED *overlapped);
|
||||
|
||||
Q_SIGNALS:
|
||||
void notified(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped);
|
||||
#if !defined(Q_QDOC)
|
||||
void _q_notify();
|
||||
|
||||
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;
|
||||
#endif
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
Loading…
Reference in New Issue
Block a user