diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-10-02 14:23:08 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-10-02 16:59:55 +0200 |
commit | d0eaa737e10aed34c09ba753e21c3e027b5ce58c (patch) | |
tree | ce2a9ea9dbfbabf5cfc390feaed5ee94beb0449a /src/corelib/kernel | |
parent | 7c0b9e1e8d069afab997efd3df9632d342b23150 (diff) | |
parent | a5f470240f31d35e694a40fe837fc4f49bc32072 (diff) |
Merge remote-tracking branch 'origin/5.5' into 5.6
Conflicts:
qmake/doc/src/qmake-manual.qdoc
src/corelib/tools/qstring.h
src/gui/image/qimagereader.cpp
src/network/access/qnetworkaccessmanager.cpp
src/tools/qdoc/doc/examples/examples.qdoc
src/widgets/accessible/qaccessiblewidgetfactory_p.h
src/widgets/doc/qtwidgets.qdocconf
Change-Id: I8fae62283aebefe24e5ca4b4abd97386560c0fcb
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 12 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication_p.h | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_win.cpp | 112 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_win_p.h | 11 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 5 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qsocketnotifier.cpp | 36 |
7 files changed, 91 insertions, 89 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 8f4774a1e0..2719019d30 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -455,8 +455,8 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint qt_application_thread_id = QThread::currentThreadId(); # endif - // note: this call to QThread::currentThread() may end up setting theMainThread! - if (QThread::currentThread() != theMainThread) + QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread! + if (cur != theMainThread) qWarning("WARNING: QApplication was not created in the main() thread."); #endif } @@ -526,11 +526,11 @@ void QCoreApplicationPrivate::eventDispatcherReady() { } -QThread *QCoreApplicationPrivate::theMainThread = 0; +QBasicAtomicPointer<QThread> QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(0); QThread *QCoreApplicationPrivate::mainThread() { - Q_ASSERT(theMainThread != 0); - return theMainThread; + Q_ASSERT(theMainThread.load() != 0); + return theMainThread.load(); } bool QCoreApplicationPrivate::threadRequiresCoreApplication() @@ -2759,7 +2759,7 @@ bool QCoreApplication::hasPendingEvents() QAbstractEventDispatcher *QCoreApplication::eventDispatcher() { if (QCoreApplicationPrivate::theMainThread) - return QCoreApplicationPrivate::theMainThread->eventDispatcher(); + return QCoreApplicationPrivate::theMainThread.load()->eventDispatcher(); return 0; } diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index 21f59d8197..9a9e8dd09a 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -105,7 +105,7 @@ public: } void maybeQuit(); - static QThread *theMainThread; + static QBasicAtomicPointer<QThread> theMainThread; static QThread *mainThread(); static bool threadRequiresCoreApplication(); diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index e8ff8a7936..ecaa78cbbc 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -390,6 +390,8 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA QSockNot *sn = dict ? dict->value(wp) : 0; if (sn) { + d->doWsaAsyncSelect(sn->fd, 0); + d->active_fd[sn->fd].selected = false; if (type < 3) { QEvent event(QEvent::SockAct); QCoreApplication::sendEvent(sn->obj, &event); @@ -632,19 +634,12 @@ void QEventDispatcherWin32Private::sendTimerEvent(int timerId) } } -void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket) +void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket, long event) { Q_ASSERT(internalHwnd); - int sn_event = 0; - if (sn_read.contains(socket)) - sn_event |= FD_READ | FD_CLOSE | FD_ACCEPT; - if (sn_write.contains(socket)) - sn_event |= FD_WRITE | FD_CONNECT; - if (sn_except.contains(socket)) - sn_event |= FD_OOB; - // BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0 + // BoundsChecker may emit a warning for WSAAsyncSelect when event == 0 // This is a BoundsChecker bug and not a Qt bug - WSAAsyncSelect(socket, internalHwnd, sn_event ? int(WM_QT_SOCKETNOTIFIER) : 0, sn_event); + WSAAsyncSelect(socket, internalHwnd, event ? int(WM_QT_SOCKETNOTIFIER) : 0, event); } void QEventDispatcherWin32::createInternalHwnd() @@ -657,13 +652,6 @@ void QEventDispatcherWin32::createInternalHwnd() installMessageHook(); - // register all socket notifiers - QList<int> sockets = (d->sn_read.keys().toSet() - + d->sn_write.keys().toSet() - + d->sn_except.keys().toSet()).toList(); - for (int i = 0; i < sockets.count(); ++i) - d->doWsaAsyncSelect(sockets.at(i)); - // start all normal timers for (int i = 0; i < d->timerVec.count(); ++i) d->registerTimer(d->timerVec.at(i)); @@ -748,28 +736,40 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) msg = d->queuedSocketEvents.takeFirst(); } else { haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE); - if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents) - && ((msg.message >= WM_KEYFIRST - && msg.message <= WM_KEYLAST) - || (msg.message >= WM_MOUSEFIRST - && msg.message <= WM_MOUSELAST) - || msg.message == WM_MOUSEWHEEL - || msg.message == WM_MOUSEHWHEEL - || msg.message == WM_TOUCH + if (haveMessage) { + if ((flags & QEventLoop::ExcludeUserInputEvents) + && ((msg.message >= WM_KEYFIRST + && msg.message <= WM_KEYLAST) + || (msg.message >= WM_MOUSEFIRST + && msg.message <= WM_MOUSELAST) + || msg.message == WM_MOUSEWHEEL + || msg.message == WM_MOUSEHWHEEL + || msg.message == WM_TOUCH #ifndef QT_NO_GESTURES - || msg.message == WM_GESTURE - || msg.message == WM_GESTURENOTIFY + || msg.message == WM_GESTURE + || msg.message == WM_GESTURENOTIFY #endif - || msg.message == WM_CLOSE)) { - // queue user input events for later processing - haveMessage = false; - d->queuedUserInputEvents.append(msg); - } - if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers) - && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) { - // queue socket events for later processing - haveMessage = false; - d->queuedSocketEvents.append(msg); + || msg.message == WM_CLOSE)) { + // queue user input events for later processing + d->queuedUserInputEvents.append(msg); + continue; + } + if ((flags & QEventLoop::ExcludeSocketNotifiers) + && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) { + // queue socket events for later processing + d->queuedSocketEvents.append(msg); + continue; + } + } else if (!(flags & QEventLoop::ExcludeSocketNotifiers)) { + // register all socket notifiers + for (QSFDict::iterator it = d->active_fd.begin(), end = d->active_fd.end(); + it != end; ++it) { + QSockFd &sd = it.value(); + if (!sd.selected) { + d->doWsaAsyncSelect(it.key(), sd.event); + sd.selected = true; + } + } } } if (!haveMessage) { @@ -895,8 +895,25 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier) sn->fd = sockfd; dict->insert(sn->fd, sn); - if (d->internalHwnd) - d->doWsaAsyncSelect(sockfd); + long event = 0; + if (d->sn_read.contains(sockfd)) + event |= FD_READ | FD_CLOSE | FD_ACCEPT; + if (d->sn_write.contains(sockfd)) + event |= FD_WRITE | FD_CONNECT; + if (d->sn_except.contains(sockfd)) + event |= FD_OOB; + + QSFDict::iterator it = d->active_fd.find(sockfd); + if (it != d->active_fd.end()) { + QSockFd &sd = it.value(); + if (sd.selected) { + d->doWsaAsyncSelect(sockfd, 0); + sd.selected = false; + } + sd.event |= event; + } else { + d->active_fd.insert(sockfd, QSockFd(event)); + } } void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) @@ -915,6 +932,19 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) #endif Q_D(QEventDispatcherWin32); + QSFDict::iterator it = d->active_fd.find(sockfd); + if (it != d->active_fd.end()) { + QSockFd &sd = it.value(); + if (sd.selected) + d->doWsaAsyncSelect(sockfd, 0); + const long event[3] = { FD_READ | FD_CLOSE | FD_ACCEPT, FD_WRITE | FD_CONNECT, FD_OOB }; + sd.event ^= event[type]; + if (sd.event == 0) + d->active_fd.erase(it); + else + sd.selected = false; + } + QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except }; QSNDict *dict = sn_vec[type]; QSockNot *sn = dict->value(sockfd); @@ -923,9 +953,6 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) dict->remove(sockfd); delete sn; - - if (d->internalHwnd) - d->doWsaAsyncSelect(sockfd); } void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) @@ -1163,6 +1190,7 @@ void QEventDispatcherWin32::closingDown() unregisterSocketNotifier((*(d->sn_write.begin()))->obj); while (!d->sn_except.isEmpty()) unregisterSocketNotifier((*(d->sn_except.begin()))->obj); + Q_ASSERT(d->active_fd.isEmpty()); // clean up any timers for (int i = 0; i < d->timerVec.count(); ++i) diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index e59e29f1ff..8578110ee4 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -115,6 +115,14 @@ struct QSockNot { }; typedef QHash<int, QSockNot *> QSNDict; +struct QSockFd { + long event; + bool selected; + + explicit inline QSockFd(long ev = 0) : event(ev), selected(false) { } +}; +typedef QHash<int, QSockFd> QSFDict; + struct WinTimerInfo { // internal timer info QObject *dispatcher; int timerId; @@ -169,7 +177,8 @@ public: QSNDict sn_read; QSNDict sn_write; QSNDict sn_except; - void doWsaAsyncSelect(int socket); + QSFDict active_fd; + void doWsaAsyncSelect(int socket, long event); QList<QWinEventNotifier *> winEventNotifierList; void activateEventNotifier(QWinEventNotifier * wen); diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 7ae9fef622..f1ad74efb4 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1547,12 +1547,13 @@ bool QMetaObject::invokeMethod(QObject *obj, /*! \fn QMetaObject::Connection &QMetaObject::Connection::operator=(Connection &&other) - Move-assigns \a other to this object. + Move-assigns \a other to this object, and returns a reference. */ /*! \fn QMetaObject::Connection::Connection(Connection &&o) - Move-constructs a Connection instance, making it point to the same object that \a o was pointing to. + Move-constructs a Connection instance, making it point to the same object + that \a o was pointing to. */ /*! diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index d324b6f150..4bd8b4b662 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1485,7 +1485,7 @@ void QObject::moveToThread(QThread *targetThread) } else if (d->threadData != currentData) { qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n" "Cannot move to target thread (%p)\n", - currentData->thread, d->threadData->thread, targetData ? targetData->thread : Q_NULLPTR); + currentData->thread.load(), d->threadData->thread.load(), targetData ? targetData->thread.load() : Q_NULLPTR); #ifdef Q_OS_MAC qWarning("You might be loading two sets of Qt binaries into the same process. " diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp index d789af2fd9..3a5eff0c19 100644 --- a/src/corelib/kernel/qsocketnotifier.cpp +++ b/src/corelib/kernel/qsocketnotifier.cpp @@ -98,42 +98,6 @@ public: QTcpSocket and QUdpSocket provide notification through signals, so there is normally no need to use a QSocketNotifier on them. - \section1 Notes for Windows Users - - The socket passed to QSocketNotifier will become non-blocking, even if - it was created as a blocking socket. - The activated() signal is sometimes triggered by high general activity - on the host, even if there is nothing to read. A subsequent read from - the socket can then fail, the error indicating that there is no data - available (e.g., \c{WSAEWOULDBLOCK}). This is an operating system - limitation, and not a bug in QSocketNotifier. - - To ensure that the socket notifier handles read notifications correctly, - follow these steps when you receive a notification: - - \list 1 - \li Disable the notifier. - \li Read data from the socket. - \li Re-enable the notifier if you are interested in more data (such as after - having written a new command to a remote server). - \endlist - - To ensure that the socket notifier handles write notifications correctly, - follow these steps when you receive a notification: - - \list 1 - \li Disable the notifier. - \li Write as much data as you can (before \c EWOULDBLOCK is returned). - \li Re-enable notifier if you have more data to write. - \endlist - - \b{Further information:} - On Windows, Qt always disables the notifier after getting a notification, - and only re-enables it if more data is expected. For example, if data is - read from the socket and it can be used to read more, or if reading or - writing is not possible because the socket would block, in which case - it is necessary to wait before attempting to read or write again. - \sa QFile, QProcess, QTcpSocket, QUdpSocket */ |