summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-10-02 14:23:08 +0200
committerLiang Qi <liang.qi@theqtcompany.com>2015-10-02 16:59:55 +0200
commitd0eaa737e10aed34c09ba753e21c3e027b5ce58c (patch)
treece2a9ea9dbfbabf5cfc390feaed5ee94beb0449a /src/corelib/kernel
parent7c0b9e1e8d069afab997efd3df9632d342b23150 (diff)
parenta5f470240f31d35e694a40fe837fc4f49bc32072 (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.cpp12
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h2
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp112
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h11
-rw-r--r--src/corelib/kernel/qmetaobject.cpp5
-rw-r--r--src/corelib/kernel/qobject.cpp2
-rw-r--r--src/corelib/kernel/qsocketnotifier.cpp36
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
*/