summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/corelib.pro9
-rw-r--r--src/corelib/doc/src/objectmodel/signalsandslots.qdoc3
-rw-r--r--src/corelib/global/qcompilerdetection.h50
-rw-r--r--src/corelib/global/qglobal.cpp2
-rw-r--r--src/corelib/global/qglobal.h7
-rw-r--r--src/corelib/global/qlibraryinfo.cpp2
-rw-r--r--src/corelib/global/qlogging.cpp7
-rw-r--r--src/corelib/global/qnamespace.h2
-rw-r--r--src/corelib/global/qnamespace.qdoc3
-rw-r--r--src/corelib/global/qsystemdetection.h3
-rw-r--r--src/corelib/global/qt_windows.h20
-rw-r--r--src/corelib/global/qtypeinfo.h4
-rw-r--r--src/corelib/io/qfilesystemiterator_win.cpp7
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp4
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify.cpp2
-rw-r--r--src/corelib/io/qprocess.h2
-rw-r--r--src/corelib/io/qprocess_win.cpp12
-rw-r--r--src/corelib/io/qsettings_win.cpp6
-rw-r--r--src/corelib/io/qstandardpaths_win.cpp22
-rw-r--r--src/corelib/io/qtextstream.cpp19
-rw-r--r--src/corelib/io/qwindowspipereader.cpp154
-rw-r--r--src/corelib/io/qwindowspipereader_p.h32
-rw-r--r--src/corelib/io/qwindowspipewriter.cpp239
-rw-r--r--src/corelib/io/qwindowspipewriter_p.h70
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.cpp28
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp4
-rw-r--r--src/corelib/json/qjson_p.h9
-rw-r--r--src/corelib/json/qjsondocument.cpp2
-rw-r--r--src/corelib/json/qjsonparser.cpp6
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp47
-rw-r--r--src/corelib/kernel/qcoreapplication.h2
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h2
-rw-r--r--src/corelib/kernel/qcoreevent.h5
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp10
-rw-r--r--src/corelib/kernel/qmetaobject.cpp27
-rw-r--r--src/corelib/kernel/qobject.h16
-rw-r--r--src/corelib/kernel/qobjectdefs.h16
-rw-r--r--src/corelib/kernel/qppsobject.cpp28
-rw-r--r--src/corelib/kernel/qppsobjectprivate_p.h4
-rw-r--r--src/corelib/kernel/qsystemsemaphore_posix.cpp4
-rw-r--r--src/corelib/kernel/qsystemsemaphore_systemv.cpp2
-rw-r--r--src/corelib/kernel/qsystemsemaphore_win.cpp6
-rw-r--r--src/corelib/mimetypes/qmimeglobpattern.cpp6
-rw-r--r--src/corelib/mimetypes/qmimeglobpattern_p.h9
-rw-r--r--src/corelib/mimetypes/qmimemagicrule.cpp13
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp5
-rw-r--r--src/corelib/mimetypes/qmimetypeparser.cpp12
-rw-r--r--src/corelib/thread/qreadwritelock.cpp528
-rw-r--r--src/corelib/thread/qreadwritelock.h6
-rw-r--r--src/corelib/thread/qreadwritelock_p.h39
-rw-r--r--src/corelib/thread/qthread.cpp5
-rw-r--r--src/corelib/thread/qthread_win.cpp6
-rw-r--r--src/corelib/thread/qwaitcondition_unix.cpp10
-rw-r--r--src/corelib/thread/qwaitcondition_win.cpp10
-rw-r--r--src/corelib/thread/thread.pri34
-rw-r--r--src/corelib/tools/qcollator_macx.cpp4
-rw-r--r--src/corelib/tools/qcollator_win.cpp2
-rw-r--r--src/corelib/tools/qhash.cpp10
-rw-r--r--src/corelib/tools/qmap.h4
-rw-r--r--src/corelib/tools/qrect.h2
-rw-r--r--src/corelib/tools/qsimd.cpp34
-rw-r--r--src/corelib/tools/qsimd_p.h33
-rw-r--r--src/corelib/tools/qstring.cpp10
-rw-r--r--src/corelib/tools/qstringbuilder.cpp24
-rw-r--r--src/corelib/tools/qstringbuilder.h6
-rw-r--r--src/corelib/tools/qtimeline.cpp2
-rw-r--r--src/corelib/tools/qtimezone.cpp4
-rw-r--r--src/corelib/tools/qtimezoneprivate_win.cpp100
-rw-r--r--src/corelib/tools/tools.pri8
69 files changed, 1175 insertions, 650 deletions
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 78ea489ebc..362ac37a59 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -7,6 +7,7 @@ MODULE_CONFIG = moc resources
!isEmpty(QT_NAMESPACE): MODULE_DEFINES = QT_NAMESPACE=$$QT_NAMESPACE
CONFIG += $$MODULE_CONFIG
+DEFINES += $$MODULE_DEFINES
DEFINES += QT_NO_USING_NAMESPACE
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x67000000
irix-cc*:QMAKE_CXXFLAGS += -no_prelink -ptused
@@ -29,7 +30,6 @@ ANDROID_PERMISSIONS = \
# variable and on FreeBSD, this variable is in the final executable itself
freebsd: QMAKE_LFLAGS_NOUNDEF =
-load(qt_module)
load(qfeatures)
include(animation/animation.pri)
@@ -58,8 +58,6 @@ mac|darwin {
LIBS_PRIVATE += -framework CoreFoundation
LIBS_PRIVATE += -framework Foundation
}
-win32:DEFINES-=QT_NO_CAST_TO_ASCII
-DEFINES += $$MODULE_DEFINES
QMAKE_LIBS += $$QMAKE_LIBS_CORE
@@ -76,6 +74,11 @@ qt_conf.variable = QT_CONFIG
QMAKE_PKGCONFIG_VARIABLES += host_bins qt_conf
+load(qt_module)
+
+# Override qt_module, so the symbols are actually included into the library.
+win32: DEFINES -= QT_NO_CAST_TO_ASCII
+
ctest_macros_file.input = $$PWD/Qt5CTestMacros.cmake
ctest_macros_file.output = $$DESTDIR/cmake/Qt5Core/Qt5CTestMacros.cmake
ctest_macros_file.CONFIG = verbatim
diff --git a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
index 6f183d3e71..216bd985db 100644
--- a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
+++ b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
@@ -251,7 +251,8 @@
This example illustrates that objects can work together without needing to
know any information about each other. To enable this, the objects only
need to be connected together, and this can be achieved with some simple
- QObject::connect() function calls, or with \c{uic}'s {automatic connections} feature.
+ QObject::connect() function calls, or with \c{uic}'s
+ \l{Automatic Connections}{automatic connections} feature.
\section1 A Real Example
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 4334539445..9a61efd1b2 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -318,14 +318,14 @@
and PGI C++ 5.2-4 */
#elif !defined(Q_OS_HPUX) && (defined(__EDG) || defined(__EDG__))
# define Q_CC_EDG
-/* From the EDG documentation (does not seem to apply to Compaq C++):
+/* From the EDG documentation (does not seem to apply to Compaq C++ or GHS C):
_BOOL
Defined in C++ mode when bool is a keyword. The name of this
predefined macro is specified by a configuration flag. _BOOL
is the default.
__BOOL_DEFINED
Defined in Microsoft C++ mode when bool is a keyword. */
-# if !defined(_BOOL) && !defined(__BOOL_DEFINED)
+# if !defined(_BOOL) && !defined(__BOOL_DEFINED) && !defined(__ghs)
# error "Compiler not supported"
# endif
@@ -347,6 +347,52 @@
/* Uses CFront, make sure to read the manual how to tweak templates. */
# elif defined(__ghs)
# define Q_CC_GHS
+# define Q_DECL_DEPRECATED __attribute__ ((__deprecated__))
+# define Q_FUNC_INFO __PRETTY_FUNCTION__
+# define Q_TYPEOF(expr) __typeof__(expr)
+# define Q_ALIGNOF(type) __alignof__(type)
+# define Q_UNREACHABLE_IMPL()
+# if defined(__cplusplus)
+# define Q_COMPILER_AUTO_TYPE
+# define Q_COMPILER_STATIC_ASSERT
+# define Q_COMPILER_RANGE_FOR
+# if __GHS_VERSION_NUMBER >= 201505
+# define Q_COMPILER_ALIGNAS
+# define Q_COMPILER_ALIGNOF
+# define Q_COMPILER_ATOMICS
+# define Q_COMPILER_ATTRIBUTES
+# define Q_COMPILER_AUTO_FUNCTION
+# define Q_COMPILER_CLASS_ENUM
+# define Q_COMPILER_CONSTEXPR
+# define Q_COMPILER_DECLTYPE
+# define Q_COMPILER_DEFAULT_MEMBERS
+# define Q_COMPILER_DELETE_MEMBERS
+# define Q_COMPILER_DELEGATING_CONSTRUCTORS
+# define Q_COMPILER_EXPLICIT_CONVERSIONS
+# define Q_COMPILER_EXPLICIT_OVERRIDES
+# define Q_COMPILER_EXTERN_TEMPLATES
+# define Q_COMPILER_INHERITING_CONSTRUCTORS
+# define Q_COMPILER_INITIALIZER_LISTS
+# define Q_COMPILER_LAMBDA
+# define Q_COMPILER_NONSTATIC_MEMBER_INIT
+# define Q_COMPILER_NOEXCEPT
+# define Q_COMPILER_NULLPTR
+# define Q_COMPILER_RANGE_FOR
+# define Q_COMPILER_RAW_STRINGS
+# define Q_COMPILER_REF_QUALIFIERS
+# define Q_COMPILER_RVALUE_REFS
+# define Q_COMPILER_STATIC_ASSERT
+# define Q_COMPILER_TEMPLATE_ALIAS
+# define Q_COMPILER_THREAD_LOCAL
+# define Q_COMPILER_THREADSAFE_STATICS
+# define Q_COMPILER_UDL
+# define Q_COMPILER_UNICODE_STRINGS
+# define Q_COMPILER_UNIFORM_INIT
+# define Q_COMPILER_UNRESTRICTED_UNIONS
+# define Q_COMPILER_VARIADIC_MACROS
+# define Q_COMPILER_VARIADIC_TEMPLATES
+# endif
+# endif //__cplusplus
# elif defined(__DCC__)
# define Q_CC_DIAB
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index cbcc6d02a6..35213f8a4c 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -426,7 +426,7 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in
*/
/*!
- \fn QFlags QFlags::setFlag(Enum flag, bool on) const
+ \fn QFlags QFlags::setFlag(Enum flag, bool on)
\since 5.7
Sets the indicated \a flag if \a on is \c true or unsets it if
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index d607b04192..86ac5d0312 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -627,6 +627,13 @@ class QDataStream;
# define QT_NO_PROCESS
#endif
+#if defined(Q_OS_INTEGRITY)
+# define QT_NO_CRASHHANDLER // no popen
+# define QT_NO_PROCESS // no exec*, no fork
+# define QT_NO_SYSTEMSEMAPHORE // not needed at all in a single AddressSpace
+# define QT_NO_MULTIPROCESS // no system
+#endif
+
inline void qt_noop(void) {}
/* These wrap try/catch so we can switch off exceptions later.
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index c962f1b4b7..458200180e 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -305,6 +305,8 @@ QLibraryInfo::buildDate()
# else
# define COMPILER_STRING "Clang " __clang_version__
# endif
+#elif defined(Q_CC_GHS)
+# define COMPILER_STRING "GHS " QT_STRINGIFY(__GHS_VERSION_NUMBER)
#elif defined(Q_CC_GNU)
# define COMPILER_STRING "GCC " __VERSION__
#elif defined(Q_CC_MSVC)
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 5e340dbd27..86aa9b9e7a 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -98,6 +98,11 @@ extern char *__progname;
#if defined(Q_OS_LINUX) && (defined(__GLIBC__) || QT_HAS_INCLUDE(<sys/syscall.h>))
# include <sys/syscall.h>
+
+# if defined(Q_OS_ANDROID) && !defined(SYS_gettid)
+# define SYS_gettid __NR_gettid
+# endif
+
static long qt_gettid()
{
// no error handling
@@ -1191,7 +1196,7 @@ static void slog2_default_handler(QtMsgType msgType, const char *message)
buffer_config.buffer_set_name = __progname;
buffer_config.num_buffers = 1;
- buffer_config.verbosity_level = SLOG2_INFO;
+ buffer_config.verbosity_level = SLOG2_DEBUG1;
buffer_config.buffer_config[0].buffer_name = "default";
buffer_config.buffer_config[0].num_pages = 8;
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 3cd3f52cff..1a3536d45b 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -1635,7 +1635,7 @@ public:
};
enum ScrollPhase {
- NoScrollPhase = 0, // Make public in 5.7 or asap
+ NoScrollPhase = 0,
ScrollBegin,
ScrollUpdate,
ScrollEnd
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index aa3fc63833..bc0e118a6f 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -3089,7 +3089,8 @@
This enum describes the phase of scrolling.
- \omitvalue NoScrollPhase The input device doesn't support scroll phase.
+ \value NoScrollPhase The input device doesn't support scroll phase.
+ This value was introduced in Qt 5.7.
\value ScrollBegin Scrolling is about to begin, but the scrolling
distance did not yet change.
diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h
index 22f01fc70b..97f750a3a6 100644
--- a/src/corelib/global/qsystemdetection.h
+++ b/src/corelib/global/qsystemdetection.h
@@ -131,6 +131,9 @@
# if defined(WINCE) || defined(_WIN32_WCE)
# define Q_OS_WINCE
# elif defined(WINAPI_FAMILY)
+# ifndef WINAPI_FAMILY_PC_APP
+# define WINAPI_FAMILY_PC_APP WINAPI_FAMILY_APP
+# endif
# if defined(WINAPI_FAMILY_PHONE_APP) && WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
# define Q_OS_WINPHONE
# define Q_OS_WINRT
diff --git a/src/corelib/global/qt_windows.h b/src/corelib/global/qt_windows.h
index f7337fe1b5..8ac3c2135d 100644
--- a/src/corelib/global/qt_windows.h
+++ b/src/corelib/global/qt_windows.h
@@ -45,22 +45,14 @@
#pragma qt_sync_stop_processing
#endif
-#if defined(Q_CC_BOR)
-// Borland's windows.h does not set these correctly, resulting in
-// unusable WinSDK standard dialogs
-#ifndef WINVER
-# define WINVER 0x0501
-#endif
-#ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0501
-#endif
-#endif
-
#if defined(Q_CC_MINGW)
// mingw's windows.h does not set _WIN32_WINNT, resulting breaking compilation
-#ifndef WINVER
-# define WINVER 0x501
-#endif
+# ifndef WINVER
+# define WINVER 0x501
+# endif
+# ifndef _WIN32_WINNT
+# define _WIN32_WINNT 0x0501
+# endif
#endif
#ifndef NOMINMAX
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index 1200c3b5a5..e709050011 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -118,14 +118,14 @@ public:
*/
// apply defaults for a generic QTypeInfo<T> that didn't provide the new values
template <typename T, typename = void>
-struct QTypeInfoQuery : QTypeInfo<T>
+struct QTypeInfoQuery : public QTypeInfo<T>
{
enum { isRelocatable = !QTypeInfo<T>::isStatic };
};
// if QTypeInfo<T>::isRelocatable exists, use it
template <typename T>
-struct QTypeInfoQuery<T, typename QtPrivate::QEnableIf<QTypeInfo<T>::isRelocatable || true>::Type> : QTypeInfo<T>
+struct QTypeInfoQuery<T, typename QtPrivate::QEnableIf<QTypeInfo<T>::isRelocatable || true>::Type> : public QTypeInfo<T>
{};
/*!
diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp
index 2caf87a7b4..ba195b2330 100644
--- a/src/corelib/io/qfilesystemiterator_win.cpp
+++ b/src/corelib/io/qfilesystemiterator_win.cpp
@@ -37,13 +37,6 @@
**
****************************************************************************/
-#if !defined(WINAPI_FAMILY)
-# if _WIN32_WINNT < 0x0500
-# undef _WIN32_WINNT
-# define _WIN32_WINNT 0x0500
-# endif // _WIN32_WINNT < 0x500
-#endif // !WINAPI_FAMILY
-
#include "qfilesystemiterator_p.h"
#include "qfilesystemengine_p.h"
#include "qplatformdefs.h"
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index e26d412cf9..8b11830fbe 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -317,11 +317,11 @@ QStringList QFileSystemWatcher::addPaths(const QStringList &paths)
// Autotest override case - use the explicitly selected engine only
const QStringRef forceName = on.midRef(26);
if(forceName == QLatin1String("poller")) {
- qDebug() << "QFileSystemWatcher: skipping native engine, using only polling engine";
+ qDebug("QFileSystemWatcher: skipping native engine, using only polling engine");
d_func()->initPollerEngine();
engine = d->poller;
} else if(forceName == QLatin1String("native")) {
- qDebug() << "QFileSystemWatcher: skipping polling engine, using only native engine";
+ qDebug("QFileSystemWatcher: skipping polling engine, using only native engine");
engine = d->native;
}
}
diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp
index 791429cc5a..5564bc7dca 100644
--- a/src/corelib/io/qfilesystemwatcher_inotify.cpp
+++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp
@@ -344,7 +344,7 @@ QStringList QInotifyFileSystemWatcherEngine::removePaths(const QStringList &path
void QInotifyFileSystemWatcherEngine::readFromInotify()
{
- // qDebug() << "QInotifyFileSystemWatcherEngine::readFromInotify";
+ // qDebug("QInotifyFileSystemWatcherEngine::readFromInotify");
int buffSize = 0;
ioctl(inotifyFd, FIONREAD, (char *) &buffSize);
diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h
index fd835d18b1..4ce0503761 100644
--- a/src/corelib/io/qprocess.h
+++ b/src/corelib/io/qprocess.h
@@ -269,7 +269,7 @@ Q_SIGNALS:
void finished(int exitCode); // ### Qt 6: merge the two signals with a default value
void finished(int exitCode, QProcess::ExitStatus exitStatus);
#if QT_DEPRECATED_SINCE(5,6)
- QT_MOC_COMPAT void error(QProcess::ProcessError error);
+ void error(QProcess::ProcessError error);
#endif
void errorOccurred(QProcess::ProcessError error);
void stateChanged(QProcess::ProcessState state, QPrivateSignal);
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 611ce34550..5d8b567c8c 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -665,7 +665,8 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
return false;
if (WaitForSingleObjectEx(pid->hProcess, 0, false) == WAIT_OBJECT_0) {
bool readyReadEmitted = drainOutputPipes();
- _q_processDied();
+ if (pid)
+ _q_processDied();
return readyReadEmitted;
}
@@ -683,10 +684,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
QIncrementalSleepTimer timer(msecs);
forever {
- // Check if we have any data pending: the pipe writer has
- // bytes waiting to written, or it has written data since the
- // last time we called stdinChannel.writer->waitForWrite().
- bool pendingDataInPipe = stdinChannel.writer && (stdinChannel.writer->bytesToWrite() || stdinChannel.writer->hadWritten());
+ bool pendingDataInPipe = stdinChannel.writer && stdinChannel.writer->bytesToWrite();
// If we don't have pending data, and our write buffer is
// empty, we fail.
@@ -770,7 +768,8 @@ bool QProcessPrivate::waitForFinished(int msecs)
if (WaitForSingleObject(pid->hProcess, timer.nextSleepTime()) == WAIT_OBJECT_0) {
drainOutputPipes();
- _q_processDied();
+ if (pid)
+ _q_processDied();
return true;
}
@@ -813,7 +812,6 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
QObjectPrivate::connect(stdinChannel.writer, &QWindowsPipeWriter::canWrite,
this, &QProcessPrivate::_q_canWrite);
- stdinChannel.writer->start();
}
return stdinChannel.writer->write(data, maxlen);
diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp
index f74f52df89..05ed51e999 100644
--- a/src/corelib/io/qsettings_win.cpp
+++ b/src/corelib/io/qsettings_win.cpp
@@ -510,6 +510,12 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
return false;
}
+ // workaround for rare cases where trailing '\0' are missing in registry
+ if (dataType == REG_SZ || dataType == REG_EXPAND_SZ)
+ dataSize += 2;
+ else if (dataType == REG_MULTI_SZ)
+ dataSize += 4;
+
// get the value
QByteArray data(dataSize, 0);
res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, 0,
diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp
index 9e3cb9ab4d..9bd5a9e3b6 100644
--- a/src/corelib/io/qstandardpaths_win.cpp
+++ b/src/corelib/io/qstandardpaths_win.cpp
@@ -117,6 +117,7 @@ static inline void appendTestMode(QString &path)
// Map QStandardPaths::StandardLocation to CLSID of SHGetSpecialFolderPath()
static int writableSpecialFolderClsid(QStandardPaths::StandardLocation type)
{
+#ifndef Q_OS_WINCE
static const int clsids[] = {
CSIDL_DESKTOPDIRECTORY, // DesktopLocation
CSIDL_PERSONAL, // DocumentsLocation
@@ -136,6 +137,27 @@ static int writableSpecialFolderClsid(QStandardPaths::StandardLocation type)
CSIDL_APPDATA, // AppDataLocation ("Roaming" path)
CSIDL_LOCAL_APPDATA, // AppConfigLocation ("Local" path)
};
+#else // !Q_OS_WINCE
+ static const int clsids[] = {
+ CSIDL_DESKTOPDIRECTORY, // DesktopLocation
+ CSIDL_PERSONAL, // DocumentsLocation
+ CSIDL_FONTS, // FontsLocation
+ CSIDL_PROGRAMS, // ApplicationsLocation
+ CSIDL_MYMUSIC, // MusicLocation
+ CSIDL_MYVIDEO, // MoviesLocation
+ CSIDL_MYPICTURES, // PicturesLocation
+ -1, -1, // TempLocation/HomeLocation
+ CSIDL_APPDATA, // AppLocalDataLocation, AppLocalDataLocation = DataLocation
+ -1, // CacheLocation
+ CSIDL_APPDATA, // GenericDataLocation
+ -1, // RuntimeLocation
+ CSIDL_APPDATA, // ConfigLocation
+ -1, -1, // DownloadLocation/GenericCacheLocation
+ CSIDL_APPDATA, // GenericConfigLocation
+ CSIDL_APPDATA, // AppDataLocation
+ CSIDL_APPDATA, // AppConfigLocation
+ };
+#endif // Q_OS_WINCE
Q_STATIC_ASSERT(sizeof(clsids) / sizeof(clsids[0]) == size_t(QStandardPaths::AppConfigLocation + 1));
return size_t(type) < sizeof(clsids) / sizeof(clsids[0]) ? clsids[type] : -1;
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index bc4a5fa538..27b7570226 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -456,6 +456,10 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
bytesRead = device->read(buf, sizeof(buf));
}
+ // reset the Text flag.
+ if (textModeEnabled)
+ device->setTextModeEnabled(true);
+
if (bytesRead <= 0)
return false;
@@ -491,10 +495,6 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
readBuffer += QString::fromLatin1(buf, bytesRead);
#endif
- // reset the Text flag.
- if (textModeEnabled)
- device->setTextModeEnabled(true);
-
// remove all '\r\n' in the string.
if (readBuffer.size() > oldReadBufferSize && textModeEnabled) {
QChar CR = QLatin1Char('\r');
@@ -593,17 +593,18 @@ void QTextStreamPrivate::flushWriteBuffer()
qDebug("QTextStreamPrivate::flushWriteBuffer(), device->write(\"%s\") == %d",
qt_prettyDebug(data.constData(), qMin(data.size(),32), data.size()).constData(), int(bytesWritten));
#endif
- if (bytesWritten <= 0) {
- status = QTextStream::WriteFailed;
- return;
- }
#if defined (Q_OS_WIN)
- // replace the text flag
+ // reset the text flag
if (textModeEnabled)
device->setTextModeEnabled(true);
#endif
+ if (bytesWritten <= 0) {
+ status = QTextStream::WriteFailed;
+ return;
+ }
+
// flush the file
#ifndef QT_NO_QOBJECT
QFileDevice *file = qobject_cast<QFileDevice *>(device);
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index 95232385b2..15fb276be9 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -38,28 +38,40 @@
****************************************************************************/
#include "qwindowspipereader_p.h"
-#include "qwinoverlappedionotifier_p.h"
-#include <qdebug.h>
+#include "qiodevice_p.h"
#include <qelapsedtimer.h>
-#include <qeventloop.h>
QT_BEGIN_NAMESPACE
+QWindowsPipeReader::Overlapped::Overlapped(QWindowsPipeReader *reader)
+ : pipeReader(reader)
+{
+}
+
+void QWindowsPipeReader::Overlapped::clear()
+{
+ ZeroMemory(this, sizeof(OVERLAPPED));
+}
+
+
QWindowsPipeReader::QWindowsPipeReader(QObject *parent)
: QObject(parent),
handle(INVALID_HANDLE_VALUE),
+ overlapped(this),
readBufferMaxSize(0),
actualReadBufferSize(0),
stopped(true),
readSequenceStarted(false),
+ notifiedCalled(false),
pipeBroken(false),
- readyReadEmitted(false)
+ readyReadPending(false),
+ inReadyRead(false)
{
- dataReadNotifier = new QWinOverlappedIoNotifier(this);
- connect(dataReadNotifier, &QWinOverlappedIoNotifier::notified, this, &QWindowsPipeReader::notified);
+ connect(this, &QWindowsPipeReader::_q_queueReadyRead,
+ this, &QWindowsPipeReader::emitPendingReadyRead, Qt::QueuedConnection);
}
-static bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped)
+bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped)
{
typedef BOOL (WINAPI *PtrCancelIoEx)(HANDLE, LPOVERLAPPED);
static PtrCancelIoEx ptrCancelIoEx = 0;
@@ -88,12 +100,6 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
actualReadBufferSize = 0;
handle = hPipeReadEnd;
pipeBroken = false;
- readyReadEmitted = false;
- stopped = false;
- if (hPipeReadEnd != INVALID_HANDLE_VALUE) {
- dataReadNotifier->setHandle(hPipeReadEnd);
- dataReadNotifier->setEnabled(true);
- }
}
/*!
@@ -104,19 +110,15 @@ void QWindowsPipeReader::stop()
{
stopped = true;
if (readSequenceStarted) {
- if (qt_cancelIo(handle, &overlapped)) {
- dataReadNotifier->waitForNotified(-1, &overlapped);
- } else {
+ if (!qt_cancelIo(handle, &overlapped)) {
const DWORD dwError = GetLastError();
if (dwError != ERROR_NOT_FOUND) {
qErrnoWarning(dwError, "QWindowsPipeReader: qt_cancelIo on handle %x failed.",
handle);
}
}
+ waitForNotification(-1);
}
- readSequenceStarted = false;
- dataReadNotifier->setEnabled(false);
- handle = INVALID_HANDLE_VALUE;
}
/*!
@@ -174,11 +176,10 @@ bool QWindowsPipeReader::canReadLine() const
\internal
Will be called whenever the read operation completes.
*/
-void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
- OVERLAPPED *notifiedOverlapped)
+void QWindowsPipeReader::notified(DWORD errorCode, DWORD numberOfBytesRead)
{
- if (&overlapped != notifiedOverlapped)
- return;
+ notifiedCalled = true;
+ readSequenceStarted = false;
switch (errorCode) {
case ERROR_SUCCESS:
@@ -202,8 +203,6 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
break;
}
- readSequenceStarted = false;
-
// After the reader was stopped, the only reason why this function can be called is the
// completion of a cancellation. No signals should be emitted, and no new read sequence should
// be started in this case.
@@ -218,13 +217,15 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
actualReadBufferSize += numberOfBytesRead;
readBuffer.truncate(actualReadBufferSize);
startAsyncRead();
- readyReadEmitted = true;
- emit readyRead();
+ if (!readyReadPending) {
+ readyReadPending = true;
+ emit _q_queueReadyRead(QWindowsPipeReader::QPrivateSignal());
+ }
}
/*!
\internal
- Reads data from the socket into the readbuffer
+ Reads data from the pipe into the readbuffer.
*/
void QWindowsPipeReader::startAsyncRead()
{
@@ -244,43 +245,41 @@ void QWindowsPipeReader::startAsyncRead()
char *ptr = readBuffer.reserve(bytesToRead);
+ stopped = false;
readSequenceStarted = true;
- ZeroMemory(&overlapped, sizeof(overlapped));
- if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) {
- // We get notified by the QWinOverlappedIoNotifier - even in the synchronous case.
- return;
- } else {
+ overlapped.clear();
+ if (!ReadFileEx(handle, ptr, bytesToRead, &overlapped, &readFileCompleted)) {
+ readSequenceStarted = false;
+
const DWORD dwError = GetLastError();
switch (dwError) {
- case ERROR_IO_PENDING:
- // This is not an error. We're getting notified, when data arrives.
- return;
- case ERROR_MORE_DATA:
- // This is not an error. The synchronous read succeeded.
- // We're connected to a message mode pipe and the message
- // didn't fit into the pipe's system buffer.
- // We're getting notified by the QWinOverlappedIoNotifier.
- break;
case ERROR_BROKEN_PIPE:
case ERROR_PIPE_NOT_CONNECTED:
- {
- // It may happen, that the other side closes the connection directly
- // after writing data. Then we must set the appropriate socket state.
- readSequenceStarted = false;
- pipeBroken = true;
- emit pipeClosed();
- return;
- }
+ // It may happen, that the other side closes the connection directly
+ // after writing data. Then we must set the appropriate socket state.
+ pipeBroken = true;
+ emit pipeClosed();
+ break;
default:
- readSequenceStarted = false;
emit winError(dwError, QLatin1String("QWindowsPipeReader::startAsyncRead"));
- return;
+ break;
}
}
}
/*!
\internal
+ Called when ReadFileEx finished the read operation.
+ */
+void QWindowsPipeReader::readFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
+ OVERLAPPED *overlappedBase)
+{
+ Overlapped *overlapped = static_cast<Overlapped *>(overlappedBase);
+ overlapped->pipeReader->notified(errorCode, numberOfBytesTransfered);
+}
+
+/*!
+ \internal
Returns the number of available bytes in the pipe.
Sets QWindowsPipeReader::pipeBroken to true if the connection is broken.
*/
@@ -298,17 +297,60 @@ DWORD QWindowsPipeReader::checkPipeState()
return 0;
}
+bool QWindowsPipeReader::waitForNotification(int timeout)
+{
+ QElapsedTimer t;
+ t.start();
+ notifiedCalled = false;
+ int msecs = timeout;
+ while (SleepEx(msecs == -1 ? INFINITE : msecs, TRUE) == WAIT_IO_COMPLETION) {
+ if (notifiedCalled)
+ return true;
+
+ // Some other I/O completion routine was called. Wait some more.
+ msecs = qt_subtract_from_timeout(timeout, t.elapsed());
+ if (!msecs)
+ break;
+ }
+ return notifiedCalled;
+}
+
+void QWindowsPipeReader::emitPendingReadyRead()
+{
+ if (readyReadPending) {
+ readyReadPending = false;
+ inReadyRead = true;
+ emit readyRead();
+ inReadyRead = false;
+ }
+}
+
/*!
Waits for the completion of the asynchronous read operation.
- Returns \c true, if we've emitted the readyRead signal.
+ Returns \c true, if we've emitted the readyRead signal (non-recursive case)
+ or readyRead will be emitted by the event loop (recursive case).
*/
bool QWindowsPipeReader::waitForReadyRead(int msecs)
{
if (!readSequenceStarted)
return false;
- readyReadEmitted = false;
- dataReadNotifier->waitForNotified(msecs, &overlapped);
- return readyReadEmitted;
+
+ if (readyReadPending) {
+ if (!inReadyRead)
+ emitPendingReadyRead();
+ return true;
+ }
+
+ if (!waitForNotification(msecs))
+ return false;
+
+ if (readyReadPending) {
+ if (!inReadyRead)
+ emitPendingReadyRead();
+ return true;
+ }
+
+ return false;
}
/*!
diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h
index d389d0cc9f..74ff5250ac 100644
--- a/src/corelib/io/qwindowspipereader_p.h
+++ b/src/corelib/io/qwindowspipereader_p.h
@@ -51,7 +51,6 @@
// We mean it.
//
-#include <qbytearray.h>
#include <qobject.h>
#include <private/qringbuffer_p.h>
@@ -59,9 +58,6 @@
QT_BEGIN_NAMESPACE
-
-class QWinOverlappedIoNotifier;
-
class Q_CORE_EXPORT QWindowsPipeReader : public QObject
{
Q_OBJECT
@@ -70,6 +66,7 @@ public:
~QWindowsPipeReader();
void setHandle(HANDLE hPipeReadEnd);
+ void startAsyncRead();
void stop();
void setMaxReadBufferSize(qint64 size) { readBufferMaxSize = size; }
@@ -82,31 +79,42 @@ public:
bool waitForReadyRead(int msecs);
bool waitForPipeClosed(int msecs);
- void startAsyncRead();
bool isReadOperationActive() const { return readSequenceStarted; }
Q_SIGNALS:
void winError(ulong, const QString &);
void readyRead();
void pipeClosed();
-
-private Q_SLOTS:
- void notified(quint32 numberOfBytesRead, quint32 errorCode, OVERLAPPED *notifiedOverlapped);
+ void _q_queueReadyRead(QPrivateSignal);
private:
+ static void CALLBACK readFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
+ OVERLAPPED *overlappedBase);
+ void notified(DWORD errorCode, DWORD numberOfBytesRead);
DWORD checkPipeState();
+ bool waitForNotification(int timeout);
+ void emitPendingReadyRead();
+
+ class Overlapped : public OVERLAPPED
+ {
+ Q_DISABLE_COPY(Overlapped)
+ public:
+ explicit Overlapped(QWindowsPipeReader *reader);
+ void clear();
+ QWindowsPipeReader *pipeReader;
+ };
-private:
HANDLE handle;
- OVERLAPPED overlapped;
- QWinOverlappedIoNotifier *dataReadNotifier;
+ Overlapped overlapped;
qint64 readBufferMaxSize;
QRingBuffer readBuffer;
qint64 actualReadBufferSize;
bool stopped;
bool readSequenceStarted;
+ bool notifiedCalled;
bool pipeBroken;
- bool readyReadEmitted;
+ bool readyReadPending;
+ bool inReadyRead;
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp
index c7144d2c6b..79e7d13eb5 100644
--- a/src/corelib/io/qwindowspipewriter.cpp
+++ b/src/corelib/io/qwindowspipewriter.cpp
@@ -38,144 +38,177 @@
****************************************************************************/
#include "qwindowspipewriter_p.h"
+#include "qiodevice_p.h"
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_THREAD
+extern bool qt_cancelIo(HANDLE handle, OVERLAPPED *overlapped); // from qwindowspipereader.cpp
-QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipe, QObject * parent)
- : QThread(parent),
- writePipe(INVALID_HANDLE_VALUE),
- quitNow(false),
- hasWritten(false)
+
+QWindowsPipeWriter::Overlapped::Overlapped(QWindowsPipeWriter *pipeWriter)
+ : pipeWriter(pipeWriter)
+{
+}
+
+void QWindowsPipeWriter::Overlapped::clear()
{
- DuplicateHandle(GetCurrentProcess(), pipe, GetCurrentProcess(),
- &writePipe, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ ZeroMemory(this, sizeof(OVERLAPPED));
+}
+
+
+QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent)
+ : QObject(parent),
+ handle(pipeWriteEnd),
+ overlapped(this),
+ numberOfBytesToWrite(0),
+ pendingBytesWrittenValue(0),
+ stopped(true),
+ writeSequenceStarted(false),
+ notifiedCalled(false),
+ bytesWrittenPending(false),
+ inBytesWritten(false)
+{
+ connect(this, &QWindowsPipeWriter::_q_queueBytesWritten,
+ this, &QWindowsPipeWriter::emitPendingBytesWrittenValue, Qt::QueuedConnection);
}
QWindowsPipeWriter::~QWindowsPipeWriter()
{
- lock.lock();
- quitNow = true;
- waitCondition.wakeOne();
- lock.unlock();
- if (!wait(30000))
- terminate();
- CloseHandle(writePipe);
+ stop();
}
bool QWindowsPipeWriter::waitForWrite(int msecs)
{
- QMutexLocker locker(&lock);
- bool hadWritten = hasWritten;
- hasWritten = false;
- if (hadWritten)
+ if (!writeSequenceStarted)
+ return false;
+
+ if (bytesWrittenPending) {
+ if (!inBytesWritten)
+ emitPendingBytesWrittenValue();
return true;
- if (!waitCondition.wait(&lock, msecs))
+ }
+
+ if (!waitForNotification(msecs))
return false;
- hadWritten = hasWritten;
- hasWritten = false;
- return hadWritten;
+
+ if (bytesWrittenPending) {
+ if (!inBytesWritten)
+ emitPendingBytesWrittenValue();
+ return true;
+ }
+
+ return false;
}
-qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen)
+qint64 QWindowsPipeWriter::bytesToWrite() const
{
- if (!isRunning())
- return -1;
-
- QMutexLocker locker(&lock);
- data.append(ptr, maxlen);
- waitCondition.wakeOne();
- return maxlen;
+ return numberOfBytesToWrite;
}
-class QPipeWriterOverlapped
+void QWindowsPipeWriter::emitPendingBytesWrittenValue()
{
-public:
- QPipeWriterOverlapped()
- {
- overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (bytesWrittenPending) {
+ bytesWrittenPending = false;
+ const qint64 bytes = pendingBytesWrittenValue;
+ pendingBytesWrittenValue = 0;
+
+ inBytesWritten = true;
+ emit bytesWritten(bytes);
+ inBytesWritten = false;
+ emit canWrite();
}
+}
- ~QPipeWriterOverlapped()
- {
- CloseHandle(overlapped.hEvent);
- }
+void QWindowsPipeWriter::writeFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
+ OVERLAPPED *overlappedBase)
+{
+ Overlapped *overlapped = static_cast<Overlapped *>(overlappedBase);
+ overlapped->pipeWriter->notified(errorCode, numberOfBytesTransfered);
+}
- void prepare()
- {
- const HANDLE hEvent = overlapped.hEvent;
- ZeroMemory(&overlapped, sizeof overlapped);
- overlapped.hEvent = hEvent;
+/*!
+ \internal
+ Will be called whenever the write operation completes.
+ */
+void QWindowsPipeWriter::notified(DWORD errorCode, DWORD numberOfBytesWritten)
+{
+ notifiedCalled = true;
+ writeSequenceStarted = false;
+ numberOfBytesToWrite = 0;
+
+ switch (errorCode) {
+ case ERROR_SUCCESS:
+ break;
+ case ERROR_OPERATION_ABORTED:
+ if (stopped)
+ break;
+ // fall through
+ default:
+ qErrnoWarning(errorCode, "QWindowsPipeWriter: asynchronous write failed.");
+ break;
}
- OVERLAPPED *operator&()
- {
- return &overlapped;
+ // After the writer was stopped, the only reason why this function can be called is the
+ // completion of a cancellation. No signals should be emitted, and no new write sequence should
+ // be started in this case.
+ if (stopped)
+ return;
+
+ pendingBytesWrittenValue += qint64(numberOfBytesWritten);
+ if (!bytesWrittenPending) {
+ bytesWrittenPending = true;
+ emit _q_queueBytesWritten(QWindowsPipeWriter::QPrivateSignal());
}
+}
-private:
- OVERLAPPED overlapped;
-};
+bool QWindowsPipeWriter::waitForNotification(int timeout)
+{
+ QElapsedTimer t;
+ t.start();
+ notifiedCalled = false;
+ int msecs = timeout;
+ while (SleepEx(msecs == -1 ? INFINITE : msecs, TRUE) == WAIT_IO_COMPLETION) {
+ if (notifiedCalled)
+ return true;
+
+ // Some other I/O completion routine was called. Wait some more.
+ msecs = qt_subtract_from_timeout(timeout, t.elapsed());
+ if (!msecs)
+ break;
+ }
+ return notifiedCalled;
+}
-void QWindowsPipeWriter::run()
+qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen)
{
- QPipeWriterOverlapped overl;
- forever {
- lock.lock();
- while(data.isEmpty() && (!quitNow)) {
- waitCondition.wakeOne();
- waitCondition.wait(&lock);
- }
+ if (writeSequenceStarted)
+ return 0;
+
+ overlapped.clear();
+ numberOfBytesToWrite = maxlen;
+ stopped = false;
+ writeSequenceStarted = true;
+ if (!WriteFileEx(handle, ptr, maxlen, &overlapped, &writeFileCompleted)) {
+ writeSequenceStarted = false;
+ qErrnoWarning("QWindowsPipeWriter::write failed.");
+ }
- if (quitNow) {
- lock.unlock();
- quitNow = false;
- break;
- }
+ return maxlen;
+}
- QByteArray copy = data;
-
- lock.unlock();
-
- const char *ptrData = copy.data();
- qint64 maxlen = copy.size();
- qint64 totalWritten = 0;
- overl.prepare();
- while ((!quitNow) && totalWritten < maxlen) {
- DWORD written = 0;
- if (!WriteFile(writePipe, ptrData + totalWritten,
- maxlen - totalWritten, &written, &overl)) {
- const DWORD writeError = GetLastError();
- if (writeError == 0xE8/*NT_STATUS_INVALID_USER_BUFFER*/) {
- // give the os a rest
- msleep(100);
- continue;
- }
- if (writeError != ERROR_IO_PENDING) {
- qErrnoWarning(writeError, "QWindowsPipeWriter: async WriteFile failed.");
- return;
- }
- if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) {
- qErrnoWarning(GetLastError(), "QWindowsPipeWriter: GetOverlappedResult failed.");
- return;
- }
+void QWindowsPipeWriter::stop()
+{
+ stopped = true;
+ if (writeSequenceStarted) {
+ if (!qt_cancelIo(handle, &overlapped)) {
+ const DWORD dwError = GetLastError();
+ if (dwError != ERROR_NOT_FOUND) {
+ qErrnoWarning(dwError, "QWindowsPipeWriter: qt_cancelIo on handle %x failed.",
+ handle);
}
- totalWritten += written;
-#if defined QPIPEWRITER_DEBUG
- qDebug("QWindowsPipeWriter::run() wrote %d %d/%d bytes",
- written, int(totalWritten), int(maxlen));
-#endif
- lock.lock();
- data.remove(0, written);
- hasWritten = true;
- lock.unlock();
}
- emit bytesWritten(totalWritten);
- emit canWrite();
+ waitForNotification(-1);
}
}
-#endif //QT_NO_THREAD
-
QT_END_NAMESPACE
diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h
index 49fb85ebdd..945cbd18bf 100644
--- a/src/corelib/io/qwindowspipewriter_p.h
+++ b/src/corelib/io/qwindowspipewriter_p.h
@@ -52,16 +52,11 @@
//
#include <qelapsedtimer.h>
-#include <qthread.h>
-#include <qmutex.h>
-#include <qwaitcondition.h>
+#include <qobject.h>
#include <qt_windows.h>
QT_BEGIN_NAMESPACE
-
-#ifndef QT_NO_THREAD
-
#define SLEEPMIN 10
#define SLEEPMAX 500
@@ -110,45 +105,50 @@ private:
int nextSleep;
};
-class Q_CORE_EXPORT QWindowsPipeWriter : public QThread
+class Q_CORE_EXPORT QWindowsPipeWriter : public QObject
{
Q_OBJECT
-
-Q_SIGNALS:
- void canWrite();
- void bytesWritten(qint64 bytes);
-
public:
- explicit QWindowsPipeWriter(HANDLE writePipe, QObject * parent = 0);
+ explicit QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent = 0);
~QWindowsPipeWriter();
- bool waitForWrite(int msecs);
qint64 write(const char *data, qint64 maxlen);
+ void stop();
+ bool waitForWrite(int msecs);
+ qint64 bytesToWrite() const;
- qint64 bytesToWrite() const
- {
- QMutexLocker locker(&lock);
- return data.size();
- }
-
- bool hadWritten() const
- {
- return hasWritten;
- }
-
-protected:
- void run();
+Q_SIGNALS:
+ void canWrite();
+ void bytesWritten(qint64 bytes);
+ void _q_queueBytesWritten(QPrivateSignal);
private:
- QByteArray data;
- QWaitCondition waitCondition;
- mutable QMutex lock;
- HANDLE writePipe;
- volatile bool quitNow;
- bool hasWritten;
-};
+ static void CALLBACK writeFileCompleted(DWORD errorCode, DWORD numberOfBytesTransfered,
+ OVERLAPPED *overlappedBase);
+ void notified(DWORD errorCode, DWORD numberOfBytesWritten);
+ bool waitForNotification(int timeout);
+ void emitPendingBytesWrittenValue();
-#endif //QT_NO_THREAD
+ class Overlapped : public OVERLAPPED
+ {
+ Q_DISABLE_COPY(Overlapped)
+ public:
+ explicit Overlapped(QWindowsPipeWriter *pipeWriter);
+ void clear();
+
+ QWindowsPipeWriter *pipeWriter;
+ };
+
+ HANDLE handle;
+ Overlapped overlapped;
+ qint64 numberOfBytesToWrite;
+ qint64 pendingBytesWrittenValue;
+ bool stopped;
+ bool writeSequenceStarted;
+ bool notifiedCalled;
+ bool bytesWrittenPending;
+ bool inBytesWritten;
+};
QT_END_NAMESPACE
diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp
index dd913f957b..b2aacfa5aa 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.cpp
+++ b/src/corelib/itemmodels/qitemselectionmodel.cpp
@@ -327,6 +327,15 @@ static void indexesFromRange(const QItemSelectionRange &range, ModelIndexContain
}
}
+template<typename ModelIndexContainer>
+static ModelIndexContainer qSelectionIndexes(const QItemSelection &selection)
+{
+ ModelIndexContainer result;
+ for (const auto &range : selection)
+ indexesFromRange(range, result);
+ return result;
+}
+
/*!
Returns \c true if the selection range contains no selectable item
\since 4.7
@@ -469,20 +478,7 @@ bool QItemSelection::contains(const QModelIndex &index) const
QModelIndexList QItemSelection::indexes() const
{
- QModelIndexList result;
- QList<QItemSelectionRange>::const_iterator it = begin();
- for (; it != end(); ++it)
- indexesFromRange(*it, result);
- return result;
-}
-
-static QVector<QPersistentModelIndex> qSelectionPersistentindexes(const QItemSelection &sel)
-{
- QVector<QPersistentModelIndex> result;
- QList<QItemSelectionRange>::const_iterator it = sel.constBegin();
- for (; it != sel.constEnd(); ++it)
- indexesFromRange(*it, result);
- return result;
+ return qSelectionIndexes<QModelIndexList>(*this);
}
static QVector<QPair<QPersistentModelIndex, uint> > qSelectionPersistentRowLengths(const QItemSelection &sel)
@@ -892,8 +888,8 @@ void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged(const QList<QPersiste
savedPersistentRowLengths = qSelectionPersistentRowLengths(ranges);
savedPersistentCurrentRowLengths = qSelectionPersistentRowLengths(currentSelection);
} else {
- savedPersistentIndexes = qSelectionPersistentindexes(ranges);
- savedPersistentCurrentIndexes = qSelectionPersistentindexes(currentSelection);
+ savedPersistentIndexes = qSelectionIndexes<QVector<QPersistentModelIndex>>(ranges);
+ savedPersistentCurrentIndexes = qSelectionIndexes<QVector<QPersistentModelIndex>>(currentSelection);
}
}
/*!
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index dc159c8f7c..18cb49d483 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -376,7 +376,7 @@ QModelIndex QSortFilterProxyModelPrivate::proxy_to_source(const QModelIndex &pro
if (!proxy_index.isValid())
return QModelIndex(); // for now; we may want to be able to set a root index later
if (proxy_index.model() != q_func()) {
- qWarning() << "QSortFilterProxyModel: index from wrong model passed to mapToSource";
+ qWarning("QSortFilterProxyModel: index from wrong model passed to mapToSource");
Q_ASSERT(!"QSortFilterProxyModel: index from wrong model passed to mapToSource");
return QModelIndex();
}
@@ -394,7 +394,7 @@ QModelIndex QSortFilterProxyModelPrivate::source_to_proxy(const QModelIndex &sou
if (!source_index.isValid())
return QModelIndex(); // for now; we may want to be able to set a root index later
if (source_index.model() != model) {
- qWarning() << "QSortFilterProxyModel: index from wrong model passed to mapFromSource";
+ qWarning("QSortFilterProxyModel: index from wrong model passed to mapFromSource");
Q_ASSERT(!"QSortFilterProxyModel: index from wrong model passed to mapFromSource");
return QModelIndex();
}
diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h
index 4c628ff1fe..e5010c2da7 100644
--- a/src/corelib/json/qjson_p.h
+++ b/src/corelib/json/qjson_p.h
@@ -151,6 +151,13 @@ public:
return *this;
}
};
+} // namespace QJsonPrivate
+
+template <typename T>
+class QTypeInfo<QJsonPrivate::q_littleendian<T> >
+ : public QTypeInfoMerger<QJsonPrivate::q_littleendian<T>, T> {};
+
+namespace QJsonPrivate {
typedef q_littleendian<short> qle_short;
typedef q_littleendian<unsigned short> qle_ushort;
@@ -402,7 +409,7 @@ public:
// pack with itself, we'll discard the high part anyway
chunk = _mm_packus_epi16(chunk, chunk);
// unaligned 64-bit store
- *(quint64*)&l[i] = _mm_cvtsi128_si64(chunk);
+ qUnalignedStore(l + i, _mm_cvtsi128_si64(chunk));
i += 8;
}
# endif
diff --git a/src/corelib/json/qjsondocument.cpp b/src/corelib/json/qjsondocument.cpp
index 1fde69ecf6..b2fa16d22a 100644
--- a/src/corelib/json/qjsondocument.cpp
+++ b/src/corelib/json/qjsondocument.cpp
@@ -184,7 +184,7 @@ QJsonDocument &QJsonDocument::operator =(const QJsonDocument &other)
QJsonDocument QJsonDocument::fromRawData(const char *data, int size, DataValidation validation)
{
if (quintptr(data) & 3) {
- qWarning() <<"QJsonDocument::fromRawData: data has to have 4 byte alignment";
+ qWarning("QJsonDocument::fromRawData: data has to have 4 byte alignment");
return QJsonDocument();
}
diff --git a/src/corelib/json/qjsonparser.cpp b/src/corelib/json/qjsonparser.cpp
index 9bafcc4c5f..2926adf10a 100644
--- a/src/corelib/json/qjsonparser.cpp
+++ b/src/corelib/json/qjsonparser.cpp
@@ -300,7 +300,7 @@ QJsonDocument Parser::parse(QJsonParseError *error)
{
#ifdef PARSER_DEBUG
indent = 0;
- qDebug() << ">>>>> parser begin";
+ qDebug(">>>>> parser begin");
#endif
// allocate some space
dataLength = qMax(end - json, (ptrdiff_t) 256);
@@ -346,7 +346,7 @@ QJsonDocument Parser::parse(QJsonParseError *error)
error:
#ifdef PARSER_DEBUG
- qDebug() << ">>>>> parser error";
+ qDebug(">>>>> parser error");
#endif
if (error) {
error->offset = json - head;
@@ -738,7 +738,7 @@ bool Parser::parseNumber(QJsonPrivate::Value *val, int baseOffset)
}
int pos = reserveSpace(sizeof(double));
- *(quint64 *)(data + pos) = qToLittleEndian(ui);
+ qToLittleEndian(ui, reinterpret_cast<uchar *>(data + pos));
if (current - baseOffset >= Value::MaxSize) {
lastError = QJsonParseError::DocumentTooLarge;
return false;
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 38efc44399..330a1eb0f5 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -674,7 +674,7 @@ QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
: QObject(p, 0)
#endif
{
- init();
+ d_func()->q_ptr = this;
// note: it is the subclasses' job to call
// QCoreApplicationPrivate::eventDispatcher->startingUp();
}
@@ -723,27 +723,26 @@ QCoreApplication::QCoreApplication(int &argc, char **argv
: QObject(*new QCoreApplicationPrivate(argc, argv, _internal))
#endif
{
- init();
+ d_func()->q_ptr = this;
+ d_func()->init();
#ifndef QT_NO_QOBJECT
QCoreApplicationPrivate::eventDispatcher->startingUp();
#endif
}
-// ### move to QCoreApplicationPrivate constructor?
-void QCoreApplication::init()
+void QCoreApplicationPrivate::init()
{
- d_ptr->q_ptr = this;
- Q_D(QCoreApplication);
+ Q_Q(QCoreApplication);
- QCoreApplicationPrivate::initLocale();
+ initLocale();
- Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
- QCoreApplication::self = this;
+ Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object");
+ QCoreApplication::self = q;
// Store app name (so it's still available after QCoreApplication is destroyed)
if (!coreappdata()->applicationNameSet)
- coreappdata()->application = d_func()->appName();
+ coreappdata()->application = appName();
QLoggingRegistry::instance()->init();
@@ -759,7 +758,7 @@ void QCoreApplication::init()
// anywhere in the list, we can just linearly scan the lists and find the items that
// have been removed. Once the original list is exhausted we know all the remaining
// items have been added.
- QStringList newPaths(libraryPaths());
+ QStringList newPaths(q->libraryPaths());
for (int i = manualPaths->length(), j = appPaths->length(); i > 0 || j > 0; qt_noop()) {
if (--j < 0) {
newPaths.prepend((*manualPaths)[--i]);
@@ -779,28 +778,28 @@ void QCoreApplication::init()
#ifndef QT_NO_QOBJECT
// use the event dispatcher created by the app programmer (if any)
- if (!QCoreApplicationPrivate::eventDispatcher)
- QCoreApplicationPrivate::eventDispatcher = d->threadData->eventDispatcher.load();
+ if (!eventDispatcher)
+ eventDispatcher = threadData->eventDispatcher.load();
// otherwise we create one
- if (!QCoreApplicationPrivate::eventDispatcher)
- d->createEventDispatcher();
- Q_ASSERT(QCoreApplicationPrivate::eventDispatcher != 0);
+ if (!eventDispatcher)
+ createEventDispatcher();
+ Q_ASSERT(eventDispatcher);
- if (!QCoreApplicationPrivate::eventDispatcher->parent()) {
- QCoreApplicationPrivate::eventDispatcher->moveToThread(d->threadData->thread);
- QCoreApplicationPrivate::eventDispatcher->setParent(this);
+ if (!eventDispatcher->parent()) {
+ eventDispatcher->moveToThread(threadData->thread);
+ eventDispatcher->setParent(q);
}
- d->threadData->eventDispatcher = QCoreApplicationPrivate::eventDispatcher;
- d->eventDispatcherReady();
+ threadData->eventDispatcher = eventDispatcher;
+ eventDispatcherReady();
#endif
#ifdef QT_EVAL
extern void qt_core_eval_init(QCoreApplicationPrivate::Type);
- qt_core_eval_init(d->application_type);
+ qt_core_eval_init(application_type);
#endif
- d->processCommandLineArguments();
+ processCommandLineArguments();
qt_call_pre_routines();
qt_startup_hook();
@@ -810,7 +809,7 @@ void QCoreApplication::init()
#endif
#ifndef QT_NO_QOBJECT
- QCoreApplicationPrivate::is_app_running = true; // No longer starting up.
+ is_app_running = true; // No longer starting up.
#endif
}
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index 3131265fd5..a22e1c4f9e 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -206,8 +206,6 @@ private:
static bool notifyInternal2(QObject *receiver, QEvent *);
#endif
- void init();
-
static QCoreApplication *self;
Q_DISABLE_COPY(QCoreApplication)
diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h
index 482429f073..445bae01b4 100644
--- a/src/corelib/kernel/qcoreapplication_p.h
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -80,6 +80,8 @@ public:
QCoreApplicationPrivate(int &aargc, char **aargv, uint flags);
~QCoreApplicationPrivate();
+ void init();
+
QString appName() const;
#ifdef Q_OS_MAC
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index 95068e6a67..7e962f816e 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -325,6 +325,11 @@ private:
friend class QGraphicsView;
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
+ // from QtTest:
+ friend class QSpontaneKeyEvent;
+ // needs this:
+ Q_ALWAYS_INLINE
+ void setSpontaneous() { spont = true; }
};
class Q_CORE_EXPORT QTimerEvent : public QEvent
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index bef105b184..a6f61afc90 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -216,8 +216,10 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
const QVector<HANDLE> timerHandles = d->timerIdToHandle.values().toVector();
if (waitTime)
emit aboutToBlock();
+ bool timerEventsSent = false;
DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, waitTime, TRUE);
- if (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) {
+ while (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) {
+ timerEventsSent = true;
const HANDLE handle = timerHandles.value(waitResult - WAIT_OBJECT_0);
ResetEvent(handle);
const int timerId = d->timerHandleToId.value(handle);
@@ -232,12 +234,10 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
// Update timer's targetTime
const quint64 targetTime = qt_msectime() + info.interval;
info.targetTime = targetTime;
- emit awake();
- return true;
+ waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, 0, TRUE);
}
emit awake();
-
- if (userEventsSent)
+ if (timerEventsSent || userEventsSent)
return true;
// We cannot wait infinitely like on other platforms, as
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 1c426225a5..4f764e7e78 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -325,6 +325,24 @@ const char *QMetaObject::className() const
\sa className()
*/
+/*
+ Returns \c true if the class described by this QMetaObject inherits
+ the type described by \a metaObject; otherwise returns false.
+
+ A type is considered to inherit itself.
+
+ \since 5.7
+*/
+bool QMetaObject::inherits(const QMetaObject *metaObject) const Q_DECL_NOEXCEPT
+{
+ const QMetaObject *m = this;
+ do {
+ if (metaObject == m)
+ return true;
+ } while ((m = m->d.superdata));
+ return false;
+}
+
/*!
\internal
@@ -345,14 +363,7 @@ QObject *QMetaObject::cast(QObject *obj) const
*/
const QObject *QMetaObject::cast(const QObject *obj) const
{
- if (obj) {
- const QMetaObject *m = obj->metaObject();
- do {
- if (m == this)
- return obj;
- } while ((m = m->d.superdata));
- }
- return 0;
+ return (obj && obj->metaObject()->inherits(this)) ? obj : nullptr;
}
#ifndef QT_NO_TRANSLATION
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index a070ddd805..1f3d3dcfc7 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -119,8 +119,8 @@ public:
Q_INVOKABLE explicit QObject(QObject *parent=Q_NULLPTR);
virtual ~QObject();
- virtual bool event(QEvent *);
- virtual bool eventFilter(QObject *, QEvent *);
+ virtual bool event(QEvent *event);
+ virtual bool eventFilter(QObject *watched, QEvent *event);
#ifdef Q_QDOC
static QString tr(const char *sourceText, const char *comment = Q_NULLPTR, int n = -1);
@@ -195,9 +195,9 @@ public:
inline const QObjectList &children() const { return d_ptr->children; }
- void setParent(QObject *);
- void installEventFilter(QObject *);
- void removeEventFilter(QObject *);
+ void setParent(QObject *parent);
+ void installEventFilter(QObject *filterObj);
+ void removeEventFilter(QObject *obj);
static QMetaObject::Connection connect(const QObject *sender, const char *signal,
const QObject *receiver, const char *member, Qt::ConnectionType = Qt::AutoConnection);
@@ -428,9 +428,9 @@ protected:
int receivers(const char* signal) const;
bool isSignalConnected(const QMetaMethod &signal) const;
- virtual void timerEvent(QTimerEvent *);
- virtual void childEvent(QChildEvent *);
- virtual void customEvent(QEvent *);
+ virtual void timerEvent(QTimerEvent *event);
+ virtual void childEvent(QChildEvent *event);
+ virtual void customEvent(QEvent *event);
virtual void connectNotify(const QMetaMethod &signal);
virtual void disconnectNotify(const QMetaMethod &signal);
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 2a6e24533a..3d47bae4a0 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -159,6 +159,12 @@ inline void qYouForgotTheQ_OBJECT_Macro(T1, T2) {}
# define Q_OBJECT_NO_OVERRIDE_WARNING
#endif
+#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 600
+# define Q_OBJECT_NO_ATTRIBUTES_WARNING QT_WARNING_DISABLE_GCC("-Wattributes")
+#else
+# define Q_OBJECT_NO_ATTRIBUTES_WARNING
+#endif
+
/* qmake ignore Q_OBJECT */
#define Q_OBJECT \
public: \
@@ -169,10 +175,11 @@ public: \
virtual const QMetaObject *metaObject() const; \
virtual void *qt_metacast(const char *); \
virtual int qt_metacall(QMetaObject::Call, int, void **); \
- QT_WARNING_POP \
QT_TR_FUNCTIONS \
private: \
+ Q_OBJECT_NO_ATTRIBUTES_WARNING \
Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
+ QT_WARNING_POP \
struct QPrivateSignal {};
/* qmake ignore Q_OBJECT */
@@ -186,7 +193,11 @@ public: \
void qt_check_for_QGADGET_macro(); \
typedef void QtGadgetHelper; \
private: \
- Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
+ QT_WARNING_PUSH \
+ Q_OBJECT_NO_ATTRIBUTES_WARNING \
+ Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
+ QT_WARNING_POP \
+ /*end*/
#endif // QT_NO_META_MACROS
#else // Q_MOC_RUN
@@ -316,6 +327,7 @@ struct Q_CORE_EXPORT QMetaObject
const char *className() const;
const QMetaObject *superClass() const;
+ bool inherits(const QMetaObject *metaObject) const Q_DECL_NOEXCEPT;
QObject *cast(QObject *obj) const;
const QObject *cast(const QObject *obj) const;
diff --git a/src/corelib/kernel/qppsobject.cpp b/src/corelib/kernel/qppsobject.cpp
index 5990deb9c3..dbff997c88 100644
--- a/src/corelib/kernel/qppsobject.cpp
+++ b/src/corelib/kernel/qppsobject.cpp
@@ -72,7 +72,7 @@ public:
{
int fd = qt_safe_open("/pps/.all", O_RDONLY);
if (fd == -1) {
- qWarning() << "qppsobject.cpp: qt_safe_open failed";
+ qWarning("qppsobject.cpp: qt_safe_open failed");
value = -1;
}
@@ -114,7 +114,7 @@ QPpsAttributeMap QPpsObjectPrivate::decode(const QByteArray &rawData, bool *ok)
// no need to check ok in this case
attributeMap = decodeObject(&decoder, ok);
} else {
- qWarning() << "QPpsObjectPrivate::decode: pps_decoder_initialize failed";
+ qWarning("QPpsObjectPrivate::decode: pps_decoder_initialize failed");
*ok = false;
}
@@ -162,7 +162,7 @@ QPpsAttribute QPpsObjectPrivate::decodeString(pps_decoder_t *decoder)
pps_decoder_error_t error = pps_decoder_get_string(decoder, 0, &value);
if (error != PPS_DECODER_OK) {
- qWarning() << "QPpsObjectPrivate::decodeString: PPS_DECODER_GET_STRING failed";
+ qWarning("QPpsObjectPrivate::decodeString: PPS_DECODER_GET_STRING failed");
return QPpsAttribute();
}
@@ -189,19 +189,19 @@ QPpsAttribute QPpsObjectPrivate::decodeNumber(pps_decoder_t *decoder)
case PPS_DECODER_CONVERSION_FAILED:
error = pps_decoder_get_int64(decoder, 0, &llValue);
if (error != PPS_DECODER_OK) {
- qWarning() << "QPpsObjectPrivate::decodeNumber: failed to decode integer";
+ qWarning("QPpsObjectPrivate::decodeNumber: failed to decode integer");
return QPpsAttribute();
}
flags = readFlags(decoder);
return QPpsAttributePrivate::createPpsAttribute(llValue, flags);
default:
- qWarning() << "QPpsObjectPrivate::decodeNumber: pps_decoder_get_int failed";
+ qWarning("QPpsObjectPrivate::decodeNumber: pps_decoder_get_int failed");
return QPpsAttribute();
}
} else {
pps_decoder_error_t error = pps_decoder_get_double(decoder, 0, &dValue);
if (error != PPS_DECODER_OK) {
- qWarning() << "QPpsObjectPrivate::decodeNumber: pps_decoder_get_double failed";
+ qWarning("QPpsObjectPrivate::decodeNumber: pps_decoder_get_double failed");
return QPpsAttribute();
}
flags = readFlags(decoder);
@@ -215,7 +215,7 @@ QPpsAttribute QPpsObjectPrivate::decodeBool(pps_decoder_t *decoder)
pps_decoder_error_t error = pps_decoder_get_bool(decoder, 0, &value);
if (error != PPS_DECODER_OK) {
- qWarning() << "QPpsObjectPrivate::decodeBool: pps_decoder_get_bool failed";
+ qWarning("QPpsObjectPrivate::decodeBool: pps_decoder_get_bool failed");
return QPpsAttribute();
}
@@ -278,7 +278,7 @@ QPpsAttribute QPpsObjectPrivate::decodeData(pps_decoder_t *decoder)
case PPS_TYPE_NONE:
case PPS_TYPE_UNKNOWN:
default:
- qWarning() << "QPpsObjectPrivate::decodeData: invalid pps_node_type";
+ qWarning("QPpsObjectPrivate::decodeData: invalid pps_node_type");
return QPpsAttribute();
}
}
@@ -292,7 +292,7 @@ QPpsAttributeList QPpsObjectPrivate::decodeArray(pps_decoder_t *decoder, bool *o
// Force movement to a specific index.
pps_decoder_error_t error = pps_decoder_goto_index(decoder, i);
if (error != PPS_DECODER_OK) {
- qWarning() << "QPpsObjectPrivate::decodeArray: pps_decoder_goto_index failed";
+ qWarning("QPpsObjectPrivate::decodeArray: pps_decoder_goto_index failed");
*ok = false;
return QPpsAttributeList();
}
@@ -319,7 +319,7 @@ QPpsAttributeMap QPpsObjectPrivate::decodeObject(pps_decoder_t *decoder, bool *o
// Force movement to a specific index.
pps_decoder_error_t error = pps_decoder_goto_index(decoder, i);
if (error != PPS_DECODER_OK) {
- qWarning() << "QPpsObjectPrivate::decodeObject: pps_decoder_goto_index failed";
+ qWarning("QPpsObjectPrivate::decodeObject: pps_decoder_goto_index failed");
*ok = false;
return QPpsAttributeMap();
}
@@ -368,7 +368,7 @@ QVariant QPpsObjectPrivate::variantFromPpsAttribute(const QPpsAttribute &attribu
return variantMapFromPpsAttributeMap(attribute.toMap());
case QPpsAttribute::None:
default:
- qWarning() << "QPpsObjectPrivate::variantFromPpsAttribute: invalid attribute parameter";
+ qWarning("QPpsObjectPrivate::variantFromPpsAttribute: invalid attribute parameter");
return QVariant();
}
}
@@ -385,7 +385,7 @@ QByteArray QPpsObjectPrivate::encode(const QVariantMap &ppsData, bool *ok)
// The memory will be freed when pps_encoder_cleanup is called.
rawData = pps_encoder_buffer(&encoder);
if (!rawData) {
- qWarning() << "QPpsObjectPrivate::encode: pps_encoder_buffer failed";
+ qWarning("QPpsObjectPrivate::encode: pps_encoder_buffer failed");
*ok = false;
}
}
@@ -448,7 +448,7 @@ void QPpsObjectPrivate::encodeData(pps_encoder_t *encoder, const char *name, con
errorFunction = QStringLiteral("pps_encoder_add_null");
break;
default:
- qWarning() << "QPpsObjectPrivate::encodeData: the type of the parameter data is invalid";
+ qWarning("QPpsObjectPrivate::encodeData: the type of the parameter data is invalid");
*ok = false;
return;
}
@@ -685,7 +685,7 @@ QByteArray QPpsObject::read(bool *ok)
const int maxSize = ppsMaxSize->value;
if (maxSize == -1) {
- qWarning() << "QPpsObject::read: maxSize is equal to -1";
+ qWarning("QPpsObject::read: maxSize is equal to -1");
safeAssign(ok, false);
return QByteArray();
}
diff --git a/src/corelib/kernel/qppsobjectprivate_p.h b/src/corelib/kernel/qppsobjectprivate_p.h
index 26d89ab7f0..e1d54e58de 100644
--- a/src/corelib/kernel/qppsobjectprivate_p.h
+++ b/src/corelib/kernel/qppsobjectprivate_p.h
@@ -105,7 +105,7 @@ inline bool QPpsObjectPrivate::decoderPush(pps_decoder_t *decoder, const char *n
{
pps_decoder_error_t error = pps_decoder_push(decoder, name);
if (error != PPS_DECODER_OK) {
- qWarning() << "QPpsObjectPrivate::decodeData: pps_decoder_push failed";
+ qWarning("QPpsObjectPrivate::decodeData: pps_decoder_push failed");
return false;
}
return true;
@@ -115,7 +115,7 @@ inline bool QPpsObjectPrivate::decoderPop(pps_decoder_t *decoder)
{
pps_decoder_error_t error = pps_decoder_pop(decoder);
if (error != PPS_DECODER_OK) {
- qWarning() << "QPpsObjectPrivate::decodeData: pps_decoder_pop failed";
+ qWarning("QPpsObjectPrivate::decodeData: pps_decoder_pop failed");
return false;
}
return true;
diff --git a/src/corelib/kernel/qsystemsemaphore_posix.cpp b/src/corelib/kernel/qsystemsemaphore_posix.cpp
index 76ab0d42eb..6137239467 100644
--- a/src/corelib/kernel/qsystemsemaphore_posix.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_posix.cpp
@@ -119,7 +119,7 @@ void QSystemSemaphorePrivate::cleanHandle()
if (::sem_close(semaphore) == -1) {
setErrorString(QLatin1String("QSystemSemaphore::cleanHandle (sem_close)"));
#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug() << QLatin1String("QSystemSemaphore::cleanHandle sem_close failed.");
+ qDebug("QSystemSemaphore::cleanHandle sem_close failed.");
#endif
}
semaphore = SEM_FAILED;
@@ -129,7 +129,7 @@ void QSystemSemaphorePrivate::cleanHandle()
if (::sem_unlink(QFile::encodeName(fileName).constData()) == -1 && errno != ENOENT) {
setErrorString(QLatin1String("QSystemSemaphore::cleanHandle (sem_unlink)"));
#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug() << QLatin1String("QSystemSemaphore::cleanHandle sem_unlink failed.");
+ qDebug("QSystemSemaphore::cleanHandle sem_unlink failed.");
#endif
}
createdSemaphore = false;
diff --git a/src/corelib/kernel/qsystemsemaphore_systemv.cpp b/src/corelib/kernel/qsystemsemaphore_systemv.cpp
index 69e1bf7705..f4fdfa5f58 100644
--- a/src/corelib/kernel/qsystemsemaphore_systemv.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_systemv.cpp
@@ -153,7 +153,7 @@ void QSystemSemaphorePrivate::cleanHandle()
if (-1 == semctl(semaphore, 0, IPC_RMID, 0)) {
setErrorString(QLatin1String("QSystemSemaphore::cleanHandle"));
#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug() << QLatin1String("QSystemSemaphore::cleanHandle semctl failed.");
+ qDebug("QSystemSemaphore::cleanHandle semctl failed.");
#endif
}
semaphore = -1;
diff --git a/src/corelib/kernel/qsystemsemaphore_win.cpp b/src/corelib/kernel/qsystemsemaphore_win.cpp
index ca31e9d59d..236e346afe 100644
--- a/src/corelib/kernel/qsystemsemaphore_win.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_win.cpp
@@ -101,7 +101,7 @@ void QSystemSemaphorePrivate::cleanHandle()
{
if (semaphore && !CloseHandle(semaphore)) {
#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug() << QLatin1String("QSystemSemaphorePrivate::CloseHandle: sem failed");
+ qDebug("QSystemSemaphorePrivate::CloseHandle: sem failed");
#endif
}
semaphore = 0;
@@ -116,7 +116,7 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count)
if (0 == ReleaseSemaphore(semaphore, count, 0)) {
setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug() << QLatin1String("QSystemSemaphore::modifySemaphore ReleaseSemaphore failed");
+ qDebug("QSystemSemaphore::modifySemaphore ReleaseSemaphore failed");
#endif
return false;
}
@@ -128,7 +128,7 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count)
#endif
setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
#if defined QSYSTEMSEMAPHORE_DEBUG
- qDebug() << QLatin1String("QSystemSemaphore::modifySemaphore WaitForSingleObject failed");
+ qDebug("QSystemSemaphore::modifySemaphore WaitForSingleObject failed");
#endif
return false;
}
diff --git a/src/corelib/mimetypes/qmimeglobpattern.cpp b/src/corelib/mimetypes/qmimeglobpattern.cpp
index 5205595943..94be5385f3 100644
--- a/src/corelib/mimetypes/qmimeglobpattern.cpp
+++ b/src/corelib/mimetypes/qmimeglobpattern.cpp
@@ -182,10 +182,8 @@ void QMimeAllGlobPatterns::addGlob(const QMimeGlobPattern &glob)
void QMimeAllGlobPatterns::removeMimeType(const QString &mimeType)
{
- QMutableHashIterator<QString, QStringList> it(m_fastPatterns);
- while (it.hasNext()) {
- it.next().value().removeAll(mimeType);
- }
+ for (auto &x : m_fastPatterns)
+ x.removeAll(mimeType);
m_highWeightGlobs.removeMimeType(mimeType);
m_lowWeightGlobs.removeMimeType(mimeType);
}
diff --git a/src/corelib/mimetypes/qmimeglobpattern_p.h b/src/corelib/mimetypes/qmimeglobpattern_p.h
index 7b4ecd2f6a..e4c74ff7fa 100644
--- a/src/corelib/mimetypes/qmimeglobpattern_p.h
+++ b/src/corelib/mimetypes/qmimeglobpattern_p.h
@@ -130,11 +130,10 @@ public:
*/
void removeMimeType(const QString &mimeType)
{
- QMutableListIterator<QMimeGlobPattern> it(*this);
- while (it.hasNext()) {
- if (it.next().mimeType() == mimeType)
- it.remove();
- }
+ auto isMimeTypeEqual = [&mimeType](const QMimeGlobPattern &pattern) {
+ return pattern.mimeType() == mimeType;
+ };
+ erase(std::remove_if(begin(), end(), isMimeTypeEqual), end());
}
void match(QMimeGlobMatchResult &result, const QString &fileName) const;
diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp
index 528dca3ff5..0db3407b7b 100644
--- a/src/corelib/mimetypes/qmimemagicrule.cpp
+++ b/src/corelib/mimetypes/qmimemagicrule.cpp
@@ -48,6 +48,7 @@
#include <QtCore/QList>
#include <QtCore/QDebug>
#include <qendian.h>
+#include <private/qsimd_p.h> // for qUnalignedLoad
QT_BEGIN_NAMESPACE
@@ -163,7 +164,7 @@ bool QMimeMagicRule::matchNumber(const QByteArray &data) const
const char *p = data.constData() + m_startPos;
const char *e = data.constData() + qMin(data.size() - int(sizeof(T)), m_endPos + 1);
for ( ; p <= e; ++p) {
- if ((*reinterpret_cast<const T*>(p) & mask) == (value & mask))
+ if ((qUnalignedLoad<T>(p) & mask) == (value & mask))
return true;
}
@@ -233,7 +234,7 @@ QMimeMagicRule::QMimeMagicRule(const QString &type,
m_mask(mask),
m_matchFunction(nullptr)
{
- if (m_type == Invalid)
+ if (Q_UNLIKELY(m_type == Invalid))
*errorString = QLatin1String("Type ") + type + QLatin1String(" is not supported");
// Parse for offset as "1" or "1:10"
@@ -246,7 +247,7 @@ QMimeMagicRule::QMimeMagicRule(const QString &type,
return;
}
- if (m_value.isEmpty()) {
+ if (Q_UNLIKELY(m_value.isEmpty())) {
m_type = Invalid;
if (errorString)
*errorString = QStringLiteral("Invalid empty magic rule value");
@@ -256,7 +257,7 @@ QMimeMagicRule::QMimeMagicRule(const QString &type,
if (m_type >= Host16 && m_type <= Byte) {
bool ok;
m_number = m_value.toUInt(&ok, 0); // autodetect base
- if (!ok) {
+ if (Q_UNLIKELY(!ok)) {
m_type = Invalid;
if (errorString)
*errorString = QLatin1String("Invalid magic rule value \"") + QLatin1String(m_value) + QLatin1Char('"');
@@ -270,7 +271,7 @@ QMimeMagicRule::QMimeMagicRule(const QString &type,
m_pattern = makePattern(m_value);
m_pattern.squeeze();
if (!m_mask.isEmpty()) {
- if (m_mask.size() < 4 || !m_mask.startsWith("0x")) {
+ if (Q_UNLIKELY(m_mask.size() < 4 || !m_mask.startsWith("0x"))) {
m_type = Invalid;
if (errorString)
*errorString = QLatin1String("Invalid magic rule mask \"") + QLatin1String(m_mask) + QLatin1Char('"');
@@ -278,7 +279,7 @@ QMimeMagicRule::QMimeMagicRule(const QString &type,
}
const QByteArray &tempMask = QByteArray::fromHex(QByteArray::fromRawData(
m_mask.constData() + 2, m_mask.size() - 2));
- if (tempMask.size() != m_pattern.size()) {
+ if (Q_UNLIKELY(tempMask.size() != m_pattern.size())) {
m_type = Invalid;
if (errorString)
*errorString = QLatin1String("Invalid magic rule mask size \"") + QLatin1String(m_mask) + QLatin1Char('"');
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index dd60c5af08..c961c25c07 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -559,7 +559,7 @@ QList<QMimeType> QMimeBinaryProvider::allMimeTypes()
void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
{
#ifdef QT_NO_XMLSTREAMREADER
- qWarning() << "Cannot load mime type since QXmlStreamReader is not available.";
+ qWarning("Cannot load mime type since QXmlStreamReader is not available.");
return;
#else
if (data.loaded)
@@ -597,9 +597,8 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
const QStringRef name = xml.attributes().value(QLatin1String("type"));
if (name.isEmpty())
continue;
- if (name != data.name) {
+ if (name.compare(data.name, Qt::CaseInsensitive))
qWarning() << "Got name" << name << "in file" << file << "expected" << data.name;
- }
while (xml.readNextStartElement()) {
const QStringRef tag = xml.name();
diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp
index 9ed345d37e..535fa51c92 100644
--- a/src/corelib/mimetypes/qmimetypeparser.cpp
+++ b/src/corelib/mimetypes/qmimetypeparser.cpp
@@ -164,7 +164,7 @@ bool QMimeTypeParserBase::parseNumber(const QStringRef &n, int *target, QString
{
bool ok;
*target = n.toInt(&ok);
- if (!ok) {
+ if (Q_UNLIKELY(!ok)) {
*errorMessage = QLatin1String("Not a number '") + n + QLatin1String("'.");
return false;
}
@@ -325,9 +325,13 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
}
}
- if (reader.hasError()) {
- if (errorMessage)
- *errorMessage = QString::fromLatin1("An error has been encountered at line %1 of %2: %3:").arg(reader.lineNumber()).arg(fileName, reader.errorString());
+ if (Q_UNLIKELY(reader.hasError())) {
+ if (errorMessage) {
+ *errorMessage = QString::asprintf("An error has been encountered at line %lld of %ls: %ls:",
+ reader.lineNumber(),
+ qUtf16Printable(fileName),
+ qUtf16Printable(reader.errorString()));
+ }
return false;
}
diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp
index 117da2e30b..5665bf74f6 100644
--- a/src/corelib/thread/qreadwritelock.cpp
+++ b/src/corelib/thread/qreadwritelock.cpp
@@ -2,6 +2,7 @@
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -45,11 +46,36 @@
#include "qmutex.h"
#include "qthread.h"
#include "qwaitcondition.h"
-
#include "qreadwritelock_p.h"
+#include "qelapsedtimer.h"
+#include "private/qfreelist_p.h"
QT_BEGIN_NAMESPACE
+/*
+ * Implementation details of QReadWriteLock:
+ *
+ * Depending on the valued of d_ptr, the lock is in the following state:
+ * - when d_ptr == 0x0: Unlocked (no readers, no writers) and non-recursive.
+ * - when d_ptr & 0x1: If the least significant bit is set, we are locked for read.
+ * In that case, d_ptr>>4 represents the number of reading threads minus 1. No writers
+ * are waiting, and the lock is not recursive.
+ * - when d_ptr == 0x2: We are locked for write and nobody is waiting. (no contention)
+ * - In any other case, d_ptr points to an actual QReadWriteLockPrivate.
+ */
+
+namespace {
+enum {
+ StateMask = 0x3,
+ StateLockedForRead = 0x1,
+ StateLockedForWrite = 0x2,
+};
+const auto dummyLockedForRead = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(StateLockedForRead));
+const auto dummyLockedForWrite = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(StateLockedForWrite));
+inline bool isUncontendedLocked(const QReadWriteLockPrivate *d)
+{ return quintptr(d) & StateMask; }
+}
+
/*! \class QReadWriteLock
\inmodule QtCore
\brief The QReadWriteLock class provides read-write locking.
@@ -116,8 +142,10 @@ QT_BEGIN_NAMESPACE
\sa lockForRead(), lockForWrite(), RecursionMode
*/
QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
- : d(new QReadWriteLockPrivate(recursionMode))
-{ }
+ : d_ptr(recursionMode == Recursive ? new QReadWriteLockPrivate(true) : nullptr)
+{
+ Q_ASSERT_X(!(quintptr(d_ptr.load()) & StateMask), "QReadWriteLock::QReadWriteLock", "bad d_ptr alignment");
+}
/*!
Destroys the QReadWriteLock object.
@@ -127,6 +155,11 @@ QReadWriteLock::QReadWriteLock(RecursionMode recursionMode)
*/
QReadWriteLock::~QReadWriteLock()
{
+ auto d = d_ptr.load();
+ if (isUncontendedLocked(d)) {
+ qWarning("QReadWriteLock: destroying locked QReadWriteLock");
+ return;
+ }
delete d;
}
@@ -141,32 +174,9 @@ QReadWriteLock::~QReadWriteLock()
*/
void QReadWriteLock::lockForRead()
{
- QMutexLocker lock(&d->mutex);
-
- Qt::HANDLE self = 0;
- if (d->recursive) {
- self = QThread::currentThreadId();
-
- QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self);
- if (it != d->currentReaders.end()) {
- ++it.value();
- ++d->accessCount;
- Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::lockForRead()",
- "Overflow in lock counter");
- return;
- }
- }
-
- while (d->accessCount < 0 || d->waitingWriters) {
- ++d->waitingReaders;
- d->readerWait.wait(&d->mutex);
- --d->waitingReaders;
- }
- if (d->recursive)
- d->currentReaders.insert(self, 1);
-
- ++d->accessCount;
- Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::lockForRead()", "Overflow in lock counter");
+ if (d_ptr.testAndSetAcquire(nullptr, dummyLockedForRead))
+ return;
+ tryLockForRead(-1);
}
/*!
@@ -187,31 +197,7 @@ void QReadWriteLock::lockForRead()
*/
bool QReadWriteLock::tryLockForRead()
{
- QMutexLocker lock(&d->mutex);
-
- Qt::HANDLE self = 0;
- if (d->recursive) {
- self = QThread::currentThreadId();
-
- QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self);
- if (it != d->currentReaders.end()) {
- ++it.value();
- ++d->accessCount;
- Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()",
- "Overflow in lock counter");
- return true;
- }
- }
-
- if (d->accessCount < 0)
- return false;
- if (d->recursive)
- d->currentReaders.insert(self, 1);
-
- ++d->accessCount;
- Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", "Overflow in lock counter");
-
- return true;
+ return tryLockForRead(0);
}
/*! \overload
@@ -235,36 +221,58 @@ bool QReadWriteLock::tryLockForRead()
*/
bool QReadWriteLock::tryLockForRead(int timeout)
{
- QMutexLocker lock(&d->mutex);
-
- Qt::HANDLE self = 0;
- if (d->recursive) {
- self = QThread::currentThreadId();
+ // Fast case: non contended:
+ QReadWriteLockPrivate *d;
+ if (d_ptr.testAndSetAcquire(nullptr, dummyLockedForRead, d))
+ return true;
+
+ while (true) {
+ if (d == 0) {
+ if (!d_ptr.testAndSetAcquire(nullptr, dummyLockedForRead, d))
+ continue;
+ return true;
+ }
- QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self);
- if (it != d->currentReaders.end()) {
- ++it.value();
- ++d->accessCount;
- Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()",
+ if ((quintptr(d) & StateMask) == StateLockedForRead) {
+ // locked for read, increase the counter
+ const auto val = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(d) + (1U<<4));
+ Q_ASSERT_X(quintptr(val) > (1U<<4), "QReadWriteLock::tryLockForRead()",
"Overflow in lock counter");
+ if (!d_ptr.testAndSetAcquire(d, val, d))
+ continue;
return true;
}
- }
- while (d->accessCount < 0 || d->waitingWriters) {
- ++d->waitingReaders;
- bool success = d->readerWait.wait(&d->mutex, timeout < 0 ? ULONG_MAX : ulong(timeout));
- --d->waitingReaders;
- if (!success)
- return false;
+ if (d == dummyLockedForWrite) {
+ // locked for write, assign a d_ptr and wait.
+ auto val = QReadWriteLockPrivate::allocate();
+ val->writerCount = 1;
+ if (!d_ptr.testAndSetOrdered(d, val, d)) {
+ val->writerCount = 0;
+ val->release();
+ continue;
+ }
+ d = val;
+ }
+ Q_ASSERT(!isUncontendedLocked(d));
+ // d is an actual pointer;
+
+ if (d->recursive)
+ return d->recursiveLockForRead(timeout);
+
+ QMutexLocker lock(&d->mutex);
+ if (d != d_ptr.load()) {
+ // d_ptr has changed: this QReadWriteLock was unlocked before we had
+ // time to lock d->mutex.
+ // We are holding a lock to a mutex within a QReadWriteLockPrivate
+ // that is already released (or even is already re-used). That's ok
+ // because the QFreeList never frees them.
+ // Just unlock d->mutex (at the end of the scope) and retry.
+ d = d_ptr.loadAcquire();
+ continue;
+ }
+ return d->lockForRead(timeout);
}
- if (d->recursive)
- d->currentReaders.insert(self, 1);
-
- ++d->accessCount;
- Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", "Overflow in lock counter");
-
- return true;
}
/*!
@@ -280,30 +288,7 @@ bool QReadWriteLock::tryLockForRead(int timeout)
*/
void QReadWriteLock::lockForWrite()
{
- QMutexLocker lock(&d->mutex);
-
- Qt::HANDLE self = 0;
- if (d->recursive) {
- self = QThread::currentThreadId();
-
- if (d->currentWriter == self) {
- --d->accessCount;
- Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::lockForWrite()",
- "Overflow in lock counter");
- return;
- }
- }
-
- while (d->accessCount != 0) {
- ++d->waitingWriters;
- d->writerWait.wait(&d->mutex);
- --d->waitingWriters;
- }
- if (d->recursive)
- d->currentWriter = self;
-
- --d->accessCount;
- Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::lockForWrite()", "Overflow in lock counter");
+ tryLockForWrite(-1);
}
/*!
@@ -323,30 +308,7 @@ void QReadWriteLock::lockForWrite()
*/
bool QReadWriteLock::tryLockForWrite()
{
- QMutexLocker lock(&d->mutex);
-
- Qt::HANDLE self = 0;
- if (d->recursive) {
- self = QThread::currentThreadId();
-
- if (d->currentWriter == self) {
- --d->accessCount;
- Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::lockForWrite()",
- "Overflow in lock counter");
- return true;
- }
- }
-
- if (d->accessCount != 0)
- return false;
- if (d->recursive)
- d->currentWriter = self;
-
- --d->accessCount;
- Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::tryLockForWrite()",
- "Overflow in lock counter");
-
- return true;
+ return tryLockForWrite(0);
}
/*! \overload
@@ -370,36 +332,48 @@ bool QReadWriteLock::tryLockForWrite()
*/
bool QReadWriteLock::tryLockForWrite(int timeout)
{
- QMutexLocker lock(&d->mutex);
-
- Qt::HANDLE self = 0;
- if (d->recursive) {
- self = QThread::currentThreadId();
-
- if (d->currentWriter == self) {
- --d->accessCount;
- Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::lockForWrite()",
- "Overflow in lock counter");
+ // Fast case: non contended:
+ QReadWriteLockPrivate *d;
+ if (d_ptr.testAndSetAcquire(nullptr, dummyLockedForWrite, d))
+ return true;
+
+ while (true) {
+ if (d == 0) {
+ if (!d_ptr.testAndSetAcquire(d, dummyLockedForWrite, d))
+ continue;
return true;
}
- }
-
- while (d->accessCount != 0) {
- ++d->waitingWriters;
- bool success = d->writerWait.wait(&d->mutex, timeout < 0 ? ULONG_MAX : ulong(timeout));
- --d->waitingWriters;
- if (!success)
- return false;
+ if (isUncontendedLocked(d)) {
+ // locked for either read or write, assign a d_ptr and wait.
+ auto val = QReadWriteLockPrivate::allocate();
+ if (d == dummyLockedForWrite)
+ val->writerCount = 1;
+ else
+ val->readerCount = (quintptr(d) >> 4) + 1;
+ if (!d_ptr.testAndSetOrdered(d, val, d)) {
+ val->writerCount = val->readerCount = 0;
+ val->release();
+ continue;
+ }
+ d = val;
+ }
+ Q_ASSERT(!isUncontendedLocked(d));
+ // d is an actual pointer;
+
+ if (d->recursive)
+ return d->recursiveLockForWrite(timeout);
+
+ QMutexLocker lock(&d->mutex);
+ if (d != d_ptr.load()) {
+ // The mutex was unlocked before we had time to lock the mutex.
+ // We are holding to a mutex within a QReadWriteLockPrivate that is already released
+ // (or even is already re-used) but that's ok because the QFreeList never frees them.
+ d = d_ptr.loadAcquire();
+ continue;
+ }
+ return d->lockForWrite(timeout);
}
- if (d->recursive)
- d->currentWriter = self;
-
- --d->accessCount;
- Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::tryLockForWrite()",
- "Overflow in lock counter");
-
- return true;
}
/*!
@@ -412,36 +386,246 @@ bool QReadWriteLock::tryLockForWrite(int timeout)
*/
void QReadWriteLock::unlock()
{
- QMutexLocker lock(&d->mutex);
+ QReadWriteLockPrivate *d = d_ptr.load();
+ while (true) {
+ Q_ASSERT_X(d, "QReadWriteLock::unlock()", "Cannot unlock an unlocked lock");
+
+ // Fast case: no contention: (no waiters, no other readers)
+ if (quintptr(d) <= 2) { // 1 or 2 (StateLockedForRead or StateLockedForWrite)
+ if (!d_ptr.testAndSetRelease(d, nullptr, d))
+ continue;
+ return;
+ }
- Q_ASSERT_X(d->accessCount != 0, "QReadWriteLock::unlock()", "Cannot unlock an unlocked lock");
+ if ((quintptr(d) & StateMask) == StateLockedForRead) {
+ Q_ASSERT(quintptr(d) > (1U<<4)); //otherwise that would be the fast case
+ // Just decrease the reader's count.
+ auto val = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(d) - (1U<<4));
+ if (!d_ptr.testAndSetRelease(d, val, d))
+ continue;
+ return;
+ }
+
+ Q_ASSERT(!isUncontendedLocked(d));
- bool unlocked = false;
- if (d->accessCount > 0) {
- // releasing a read lock
if (d->recursive) {
- Qt::HANDLE self = QThread::currentThreadId();
- QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self);
- if (it != d->currentReaders.end()) {
- if (--it.value() <= 0)
- d->currentReaders.erase(it);
+ d->recursiveUnlock();
+ return;
+ }
+
+ QMutexLocker locker(&d->mutex);
+ if (d->writerCount) {
+ Q_ASSERT(d->writerCount == 1);
+ Q_ASSERT(d->readerCount == 0);
+ d->writerCount = 0;
+ } else {
+ Q_ASSERT(d->readerCount > 0);
+ d->readerCount--;
+ if (d->readerCount > 0)
+ return;
+ }
+
+ if (d->waitingReaders || d->waitingWriters) {
+ d->unlock();
+ } else {
+ Q_ASSERT(d_ptr.load() == d); // should not change when we still hold the mutex
+ d_ptr.storeRelease(nullptr);
+ d->release();
+ }
+ return;
+ }
+}
+
+/*! \internal Helper for QWaitCondition::wait */
+QReadWriteLock::StateForWaitCondition QReadWriteLock::stateForWaitCondition() const
+{
+ QReadWriteLockPrivate *d = d_ptr.load();
+ switch (quintptr(d) & StateMask) {
+ case StateLockedForRead: return LockedForRead;
+ case StateLockedForWrite: return LockedForWrite;
+ }
+
+ if (!d)
+ return Unlocked;
+ if (d->writerCount > 1)
+ return RecursivelyLocked;
+ else if (d->writerCount == 1)
+ return LockedForWrite;
+ return LockedForRead;
+
+}
+
+bool QReadWriteLockPrivate::lockForRead(int timeout)
+{
+ Q_ASSERT(!mutex.tryLock()); // mutex must be locked when entering this function
+
+ QElapsedTimer t;
+ if (timeout > 0)
+ t.start();
+
+ while (waitingWriters || writerCount) {
+ if (timeout == 0)
+ return false;
+ if (timeout > 0) {
+ auto elapsed = t.elapsed();
+ if (elapsed > timeout)
+ return false;
+ waitingReaders++;
+ readerCond.wait(&mutex, timeout - elapsed);
+ } else {
+ waitingReaders++;
+ readerCond.wait(&mutex);
+ }
+ waitingReaders--;
+ }
+ readerCount++;
+ Q_ASSERT(writerCount == 0);
+ return true;
+}
+
+bool QReadWriteLockPrivate::lockForWrite(int timeout)
+{
+ Q_ASSERT(!mutex.tryLock()); // mutex must be locked when entering this function
+
+ QElapsedTimer t;
+ if (timeout > 0)
+ t.start();
+
+ while (readerCount || writerCount) {
+ if (timeout == 0)
+ return false;
+ if (timeout > 0) {
+ auto elapsed = t.elapsed();
+ if (elapsed > timeout) {
+ if (waitingReaders && !waitingWriters && !writerCount) {
+ // We timed out and now there is no more writers or waiting writers, but some
+ // readers were queueud (probably because of us). Wake the waiting readers.
+ readerCond.wakeAll();
+ }
+ return false;
}
+ waitingWriters++;
+ writerCond.wait(&mutex, timeout - elapsed);
+ } else {
+ waitingWriters++;
+ writerCond.wait(&mutex);
}
+ waitingWriters--;
+ }
+
+ Q_ASSERT(writerCount == 0);
+ Q_ASSERT(readerCount == 0);
+ writerCount = 1;
+ return true;
+}
+
+void QReadWriteLockPrivate::unlock()
+{
+ Q_ASSERT(!mutex.tryLock()); // mutex must be locked when entering this function
+ if (waitingWriters)
+ writerCond.wakeOne();
+ else if (waitingReaders)
+ readerCond.wakeAll();
+}
+
+bool QReadWriteLockPrivate::recursiveLockForRead(int timeout)
+{
+ Q_ASSERT(recursive);
+ QMutexLocker lock(&mutex);
+
+ Qt::HANDLE self = QThread::currentThreadId();
+
+ auto it = currentReaders.find(self);
+ if (it != currentReaders.end()) {
+ ++it.value();
+ return true;
+ }
- unlocked = --d->accessCount == 0;
- } else if (d->accessCount < 0 && ++d->accessCount == 0) {
- // released a write lock
- unlocked = true;
- d->currentWriter = 0;
+ if (!lockForRead(timeout))
+ return false;
+
+ currentReaders.insert(self, 1);
+ return true;
+}
+
+bool QReadWriteLockPrivate::recursiveLockForWrite(int timeout)
+{
+ Q_ASSERT(recursive);
+ QMutexLocker lock(&mutex);
+
+ Qt::HANDLE self = QThread::currentThreadId();
+ if (currentWriter == self) {
+ writerCount++;
+ return true;
}
- if (unlocked) {
- if (d->waitingWriters) {
- d->writerWait.wakeOne();
- } else if (d->waitingReaders) {
- d->readerWait.wakeAll();
+ if (!lockForWrite(timeout))
+ return false;
+
+ currentWriter = self;
+ return true;
+}
+
+void QReadWriteLockPrivate::recursiveUnlock()
+{
+ Q_ASSERT(recursive);
+ QMutexLocker lock(&mutex);
+
+ Qt::HANDLE self = QThread::currentThreadId();
+ if (self == currentWriter) {
+ if (--writerCount > 0)
+ return;
+ currentWriter = 0;
+ } else {
+ auto it = currentReaders.find(self);
+ if (it == currentReaders.end()) {
+ qWarning("QReadWriteLock::unlock: unlocking from a thread that did not lock");
+ return;
+ } else {
+ if (--it.value() <= 0) {
+ currentReaders.erase(it);
+ readerCount--;
+ }
+ if (readerCount)
+ return;
}
}
+
+ unlock();
+}
+
+// The freelist management
+namespace {
+struct FreeListConstants : QFreeListDefaultConstants {
+ enum { BlockCount = 4, MaxIndex=0xffff };
+ static const int Sizes[BlockCount];
+};
+const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = {
+ 16,
+ 128,
+ 1024,
+ FreeListConstants::MaxIndex - (16 + 128 + 1024)
+};
+
+typedef QFreeList<QReadWriteLockPrivate, FreeListConstants> FreeList;
+Q_GLOBAL_STATIC(FreeList, freelist);
+}
+
+QReadWriteLockPrivate *QReadWriteLockPrivate::allocate()
+{
+ int i = freelist->next();
+ QReadWriteLockPrivate *d = &(*freelist)[i];
+ d->id = i;
+ Q_ASSERT(!d->recursive);
+ Q_ASSERT(!d->waitingReaders && !d->waitingReaders && !d->readerCount && !d->writerCount);
+ return d;
+}
+
+void QReadWriteLockPrivate::release()
+{
+ Q_ASSERT(!recursive);
+ Q_ASSERT(!waitingReaders && !waitingReaders && !readerCount && !writerCount);
+ freelist->release(id);
}
/*!
diff --git a/src/corelib/thread/qreadwritelock.h b/src/corelib/thread/qreadwritelock.h
index b7e2092e38..777efdb3bf 100644
--- a/src/corelib/thread/qreadwritelock.h
+++ b/src/corelib/thread/qreadwritelock.h
@@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_THREAD
-struct QReadWriteLockPrivate;
+class QReadWriteLockPrivate;
class Q_CORE_EXPORT QReadWriteLock
{
@@ -69,8 +69,10 @@ public:
private:
Q_DISABLE_COPY(QReadWriteLock)
- QReadWriteLockPrivate *d;
+ QAtomicPointer<QReadWriteLockPrivate> d_ptr;
+ enum StateForWaitCondition { LockedForRead, LockedForWrite, Unlocked, RecursivelyLocked };
+ StateForWaitCondition stateForWaitCondition() const;
friend class QWaitCondition;
};
diff --git a/src/corelib/thread/qreadwritelock_p.h b/src/corelib/thread/qreadwritelock_p.h
index 1f6f73c8e3..285f017655 100644
--- a/src/corelib/thread/qreadwritelock_p.h
+++ b/src/corelib/thread/qreadwritelock_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -53,29 +54,47 @@
#include <QtCore/qglobal.h>
#include <QtCore/qhash.h>
+#include <QtCore/QWaitCondition>
#ifndef QT_NO_THREAD
QT_BEGIN_NAMESPACE
-struct QReadWriteLockPrivate
+class QReadWriteLockPrivate
{
- QReadWriteLockPrivate(QReadWriteLock::RecursionMode recursionMode)
- : accessCount(0), waitingReaders(0), waitingWriters(0),
- recursive(recursionMode == QReadWriteLock::Recursive), currentWriter(0)
- { }
+public:
+ QReadWriteLockPrivate(bool isRecursive = false)
+ : readerCount(0), writerCount(0), waitingReaders(0), waitingWriters(0),
+ recursive(isRecursive), id(0) {}
QMutex mutex;
- QWaitCondition readerWait;
- QWaitCondition writerWait;
-
- int accessCount;
+ QWaitCondition writerCond;
+ QWaitCondition readerCond;
+ int readerCount;
+ int writerCount;
int waitingReaders;
int waitingWriters;
-
bool recursive;
+
+ //Called with the mutex locked
+ bool lockForWrite(int timeout);
+ bool lockForRead(int timeout);
+ void unlock();
+
+ //memory management
+ int id;
+ void release();
+ static QReadWriteLockPrivate *allocate();
+
+ // Recusive mutex handling
Qt::HANDLE currentWriter;
QHash<Qt::HANDLE, int> currentReaders;
+
+ // called with the mutex unlocked
+ bool recursiveLockForWrite(int timeout);
+ bool recursiveLockForRead(int timeout);
+ void recursiveUnlock();
+
};
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index 48b94abae5..8a797772fc 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -310,8 +310,9 @@ QThreadPrivate::~QThreadPrivate()
The effect of the \a priority parameter is dependent on the
operating system's scheduling policy. In particular, the \a priority
will be ignored on systems that do not support thread priorities
- (such as on Linux, see http://linux.die.net/man/2/sched_setscheduler
- for more details).
+ (such as on Linux, see the
+ \l {http://linux.die.net/man/2/sched_setscheduler}{sched_setscheduler}
+ documentation for more details).
\sa run(), terminate()
*/
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index 635282d5c4..ef1799a021 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -37,12 +37,6 @@
**
****************************************************************************/
-//#define WINVER 0x0500
-#if !defined(WINAPI_FAMILY) && (_WIN32_WINNT < 0x0400)
-#define _WIN32_WINNT 0x0400
-#endif
-
-
#include "qthread.h"
#include "qthread_p.h"
#include "qthreadstorage.h"
diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp
index 2a98fd2897..6adee5412e 100644
--- a/src/corelib/thread/qwaitcondition_unix.cpp
+++ b/src/corelib/thread/qwaitcondition_unix.cpp
@@ -221,9 +221,12 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
{
- if (!readWriteLock || readWriteLock->d->accessCount == 0)
+ if (!readWriteLock)
return false;
- if (readWriteLock->d->accessCount < -1) {
+ auto previousState = readWriteLock->stateForWaitCondition();
+ if (previousState == QReadWriteLock::Unlocked)
+ return false;
+ if (previousState == QReadWriteLock::RecursivelyLocked) {
qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()");
return false;
}
@@ -231,12 +234,11 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wait()", "mutex lock");
++d->waiters;
- int previousAccessCount = readWriteLock->d->accessCount;
readWriteLock->unlock();
bool returnValue = d->wait(time);
- if (previousAccessCount < 0)
+ if (previousState == QReadWriteLock::LockedForWrite)
readWriteLock->lockForWrite();
else
readWriteLock->lockForRead();
diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp
index 246e45a54c..f3a645c504 100644
--- a/src/corelib/thread/qwaitcondition_win.cpp
+++ b/src/corelib/thread/qwaitcondition_win.cpp
@@ -191,20 +191,22 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
{
- if (!readWriteLock || readWriteLock->d->accessCount == 0)
+ if (!readWriteLock)
return false;
- if (readWriteLock->d->accessCount < -1) {
+ auto previousState = readWriteLock->stateForWaitCondition();
+ if (previousState == QReadWriteLock::Unlocked)
+ return false;
+ if (previousState == QReadWriteLock::RecursivelyLocked) {
qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()");
return false;
}
QWaitConditionEvent *wce = d->pre();
- int previousAccessCount = readWriteLock->d->accessCount;
readWriteLock->unlock();
bool returnValue = d->wait(wce, time);
- if (previousAccessCount < 0)
+ if (previousState == QReadWriteLock::LockedForWrite)
readWriteLock->lockForWrite();
else
readWriteLock->lockForRead();
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
index 2cb00a6cf4..0a989cfcaf 100644
--- a/src/corelib/thread/thread.pri
+++ b/src/corelib/thread/thread.pri
@@ -43,24 +43,20 @@ SOURCES += thread/qatomic.cpp \
thread/qthreadpool.cpp \
thread/qthreadstorage.cpp
-unix:SOURCES += thread/qthread_unix.cpp \
- thread/qwaitcondition_unix.cpp
-
-win32:SOURCES += thread/qthread_win.cpp \
- thread/qwaitcondition_win.cpp
-
-integrity:SOURCES += thread/qthread_unix.cpp \
- thread/qwaitcondition_unix.cpp
-
-false {
- # files #included by others, but listed here so IDEs parsing this file know
- # they are part of QtCore. Usually, qmake can find out that certain files
- # are #included by others and thus remove from SOURCES, but it gets lost
- # with qmutex.cpp.
+win32 {
SOURCES += \
- thread/qmutex_linux.cpp \
- thread/qmutex_mac.cpp \
- thread/qmutex_unix.cpp \
- thread/qmutex_win.cpp
+ thread/qmutex_win.cpp \
+ thread/qthread_win.cpp \
+ thread/qwaitcondition_win.cpp
+} else {
+ darwin {
+ SOURCES += thread/qmutex_mac.cpp
+ } else: linux {
+ SOURCES += thread/qmutex_linux.cpp
+ } else {
+ SOURCES += thread/qmutex_unix.cpp
+ }
+ SOURCES += \
+ thread/qthread_unix.cpp \
+ thread/qwaitcondition_unix.cpp
}
-
diff --git a/src/corelib/tools/qcollator_macx.cpp b/src/corelib/tools/qcollator_macx.cpp
index 207b5bb2b1..b4d93e58d4 100644
--- a/src/corelib/tools/qcollator_macx.cpp
+++ b/src/corelib/tools/qcollator_macx.cpp
@@ -55,7 +55,7 @@ void QCollatorPrivate::init()
LocaleRef localeRef;
int rc = LocaleRefFromLocaleString(locale.bcp47Name().toLocal8Bit(), &localeRef);
if (rc != 0)
- qWarning() << "couldn't initialize the locale";
+ qWarning("couldn't initialize the locale");
UInt32 options = 0;
@@ -73,7 +73,7 @@ void QCollatorPrivate::init()
&collator
);
if (status != 0)
- qWarning() << "Couldn't initialize the collator";
+ qWarning("Couldn't initialize the collator");
dirty = false;
}
diff --git a/src/corelib/tools/qcollator_win.cpp b/src/corelib/tools/qcollator_win.cpp
index 30e358c3f9..fcd8d069eb 100644
--- a/src/corelib/tools/qcollator_win.cpp
+++ b/src/corelib/tools/qcollator_win.cpp
@@ -73,7 +73,7 @@ void QCollatorPrivate::init()
if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7)
collator |= SORT_DIGITSASNUMBERS;
else
- qWarning() << "Numeric sorting unsupported on Windows versions older than Windows 7.";
+ qWarning("Numeric sorting unsupported on Windows versions older than Windows 7.");
}
if (ignorePunctuation)
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index b49c9d683a..8ab98bd509 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -113,31 +113,31 @@ static uint crc32(const Char *ptr, size_t len, uint h)
p += 8;
for ( ; p <= e; p += 8)
- h2 = _mm_crc32_u64(h2, *reinterpret_cast<const qlonglong *>(p - 8));
+ h2 = _mm_crc32_u64(h2, qUnalignedLoad<qlonglong>(p - 8));
h = h2;
p -= 8;
len = e - p;
if (len & 4) {
- h = _mm_crc32_u32(h, *reinterpret_cast<const uint *>(p));
+ h = _mm_crc32_u32(h, qUnalignedLoad<uint>(p));
p += 4;
}
# else
p += 4;
for ( ; p <= e; p += 4)
- h = _mm_crc32_u32(h, *reinterpret_cast<const uint *>(p - 4));
+ h = _mm_crc32_u32(h, qUnalignedLoad<uint>(p - 4));
p -= 4;
len = e - p;
# endif
if (len & 2) {
- h = _mm_crc32_u16(h, *reinterpret_cast<const ushort *>(p));
+ h = _mm_crc32_u16(h, qUnalignedLoad<ushort>(p));
p += 2;
}
if (sizeof(Char) == 1 && len & 1)
h = _mm_crc32_u8(h, *p);
return h;
}
-#elif defined(Q_PROCESSOR_ARM_V8)
+#elif defined(__ARM_FEATURE_CRC32)
static inline bool hasFastCrc32()
{
return qCpuHasFeature(CRC32);
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index 7eec281957..9801878bdc 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -909,7 +909,7 @@ template <class Key, class T>
void QMap<Key, T>::dump() const
{
const_iterator it = begin();
- qDebug() << "map dump:";
+ qDebug("map dump:");
while (it != end()) {
const QMapNodeBase *n = it.i;
int depth = 0;
@@ -922,7 +922,7 @@ void QMap<Key, T>::dump() const
<< it.key() << it.value();
++it;
}
- qDebug() << "---------";
+ qDebug("---------");
}
#endif
diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h
index 31fdc8ce6b..b376b6b999 100644
--- a/src/corelib/tools/qrect.h
+++ b/src/corelib/tools/qrect.h
@@ -252,7 +252,7 @@ Q_DECL_CONSTEXPR inline QPoint QRect::bottomLeft() const Q_DECL_NOTHROW
{ return QPoint(x1, y2); }
Q_DECL_CONSTEXPR inline QPoint QRect::center() const Q_DECL_NOTHROW
-{ return QPoint((x1+x2)/2, (y1+y2)/2); }
+{ return QPoint(int((qint64(x1)+x2)/2), int((qint64(y1)+y2)/2)); } // cast avoids overflow on addition
Q_DECL_CONSTEXPR inline int QRect::width() const Q_DECL_NOTHROW
{ return x2 - x1 + 1; }
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
index f2caaaa538..9037442d9d 100644
--- a/src/corelib/tools/qsimd.cpp
+++ b/src/corelib/tools/qsimd.cpp
@@ -117,13 +117,7 @@ static inline quint64 detectProcessorFeatures()
{
quint64 features = 0;
-#if defined(Q_OS_IOS)
- features |= Q_UINT64_C(1) << CpuFeatureNEON; // On iOS, NEON is always available.
-# ifdef Q_PROCESSOR_ARM_V8
- features |= Q_UINT64_C(1) << CpuFeatureCRC32; // On iOS, crc32 is always available if the architecture is Aarch32/64.
-# endif
- return features;
-#elif defined(Q_OS_LINUX)
+#if defined(Q_OS_LINUX)
# if defined(Q_PROCESSOR_ARM_V8) && defined(Q_PROCESSOR_ARM_64)
features |= Q_UINT64_C(1) << CpuFeatureNEON; // NEON is always available on ARMv8 64bit.
# endif
@@ -167,10 +161,10 @@ static inline quint64 detectProcessorFeatures()
#endif
#if defined(__ARM_NEON__)
- features = Q_UINT64_C(1) << CpuFeatureNEON;
+ features |= Q_UINT64_C(1) << CpuFeatureNEON;
#endif
#if defined(__ARM_FEATURE_CRC32)
- features = Q_UINT64_C(1) << CpuFeatureCRC32;
+ features |= Q_UINT64_C(1) << CpuFeatureCRC32;
#endif
return features;
@@ -753,4 +747,26 @@ void qDumpCPUFeatures()
puts("");
}
+/*!
+ \internal
+ \fn T qUnalignedLoad(const void *ptr)
+ \since 5.6.1
+
+ Loads a \c{T} from address \a ptr, which may be misaligned.
+
+ Use of this function avoid the undefined behavior that the C++ standard
+ otherwise attributes to unaligned loads.
+*/
+
+/*!
+ \internal
+ \fn void qUnalignedStore(void *ptr, T t)
+ \since 5.6.1
+
+ Stores \a t to address \a ptr, which may be misaligned.
+
+ Use of this function avoid the undefined behavior that the C++ standard
+ otherwise attributes to unaligned stores.
+*/
+
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
index c771037427..1a795a670d 100644
--- a/src/corelib/tools/qsimd_p.h
+++ b/src/corelib/tools/qsimd_p.h
@@ -267,6 +267,13 @@
# endif
#endif
+// Clang compiler fix, see http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20160222/151168.html
+// This should be tweaked with an "upper version" of clang once we know which release fixes the
+// issue. At that point we can rely on __ARM_FEATURE_CRC32 again.
+#if defined(Q_CC_CLANG) && defined(Q_OS_DARWIN) && defined (__ARM_FEATURE_CRC32)
+# undef __ARM_FEATURE_CRC32
+#endif
+
// NEON intrinsics
// note: as of GCC 4.9, does not support function targets for ARM
#if defined(__ARM_NEON) || defined(__ARM_NEON__)
@@ -514,6 +521,32 @@ unsigned _bit_scan_forward(unsigned val)
#define ALIGNMENT_PROLOGUE_16BYTES(ptr, i, length) \
for (; i < static_cast<int>(qMin(static_cast<quintptr>(length), ((4 - ((reinterpret_cast<quintptr>(ptr) >> 2) & 0x3)) & 0x3))); ++i)
+template <typename T>
+Q_ALWAYS_INLINE
+T qUnalignedLoad(const void *ptr) Q_DECL_NOTHROW
+{
+ T result;
+#if QT_HAS_BUILTIN(__builtin_memcpy)
+ __builtin_memcpy
+#else
+ memcpy
+#endif
+ /*memcpy*/(&result, ptr, sizeof result);
+ return result;
+}
+
+template <typename T>
+Q_ALWAYS_INLINE
+void qUnalignedStore(void *ptr, T t) Q_DECL_NOTHROW
+{
+#if QT_HAS_BUILTIN(__builtin_memcpy)
+ __builtin_memcpy
+#else
+ memcpy
+#endif
+ /*memcpy*/(ptr, &t, sizeof t);
+}
+
QT_END_NAMESPACE
#endif // QSIMD_P_H
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 18435c3009..5c6ce179d0 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -584,7 +584,7 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l)
// we'll read uc[offset..offset+7] (16 bytes) and c[offset..offset+7] (8 bytes)
if (uc + offset + 7 < e) {
// same, but we're using an 8-byte load
- __m128i chunk = _mm_cvtsi64_si128(*(const long long *)(c + offset));
+ __m128i chunk = _mm_cvtsi64_si128(qUnalignedLoad<long long>(c + offset));
__m128i secondHalf = _mm_unpacklo_epi8(chunk, nullmask);
__m128i ucdata = _mm_loadu_si128((const __m128i*)(uc + offset));
@@ -6177,11 +6177,7 @@ QString QString::vasprintf(const char *cformat, va_list ap)
}
case 'p': {
void *arg = va_arg(ap, void*);
-#ifdef Q_OS_WIN64
- quint64 i = reinterpret_cast<quint64>(arg);
-#else
- quint64 i = reinterpret_cast<unsigned long>(arg);
-#endif
+ const quint64 i = reinterpret_cast<quintptr>(arg);
flags |= QLocaleData::Alternate;
subst = QLocaleData::c()->unsLongLongToString(i, precision, 16, width, flags);
++c;
@@ -10681,7 +10677,7 @@ QString QString::toHtmlEscaped() const
/*!
\internal
*/
-void QAbstractConcatenable::appendLatin1To(const char *a, int len, QChar *out)
+void QAbstractConcatenable::appendLatin1To(const char *a, int len, QChar *out) Q_DECL_NOTHROW
{
qt_from_latin1(reinterpret_cast<ushort *>(out), a, uint(len));
}
diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp
index eba939a413..de12de19cb 100644
--- a/src/corelib/tools/qstringbuilder.cpp
+++ b/src/corelib/tools/qstringbuilder.cpp
@@ -39,6 +39,7 @@
#include "qstringbuilder.h"
#include <QtCore/qtextcodec.h>
+#include <private/qutfcodec_p.h>
QT_BEGIN_NAMESPACE
@@ -107,29 +108,14 @@ QT_BEGIN_NAMESPACE
/*!
\internal
*/
-void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out)
+void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out) Q_DECL_NOTHROW
{
- if (len == -1) {
+ if (Q_UNLIKELY(len == -1)) {
if (!a)
return;
- while (*a && uchar(*a) < 0x80U)
- *out++ = QLatin1Char(*a++);
- if (!*a)
- return;
- } else {
- int i;
- for (i = 0; i < len && uchar(a[i]) < 0x80U; ++i)
- *out++ = QLatin1Char(a[i]);
- if (i == len)
- return;
- a += i;
- len -= i;
+ len = int(strlen(a));
}
-
- // we need to complement with UTF-8 appending
- QString tmp = QString::fromUtf8(a, len);
- memcpy(out, reinterpret_cast<const char *>(tmp.constData()), sizeof(QChar) * tmp.size());
- out += tmp.size();
+ out = QUtf8::convertToUnicode(out, a, len);
}
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
index faf9eb4b4d..8ce98cbd71 100644
--- a/src/corelib/tools/qstringbuilder.h
+++ b/src/corelib/tools/qstringbuilder.h
@@ -58,12 +58,12 @@ QT_BEGIN_NAMESPACE
struct Q_CORE_EXPORT QAbstractConcatenable
{
protected:
- static void convertFromAscii(const char *a, int len, QChar *&out);
- static inline void convertFromAscii(char a, QChar *&out)
+ static void convertFromAscii(const char *a, int len, QChar *&out) Q_DECL_NOTHROW;
+ static inline void convertFromAscii(char a, QChar *&out) Q_DECL_NOTHROW
{
*out++ = QLatin1Char(a);
}
- static void appendLatin1To(const char *a, int len, QChar *out);
+ static void appendLatin1To(const char *a, int len, QChar *out) Q_DECL_NOTHROW;
};
template <typename T> struct QConcatenable {};
diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp
index dd6a4dbc56..adbc2900e3 100644
--- a/src/corelib/tools/qtimeline.cpp
+++ b/src/corelib/tools/qtimeline.cpp
@@ -131,7 +131,7 @@ void QTimeLinePrivate::setCurrentTime(int msecs)
const int transitionframe = (direction == QTimeLine::Forward ? endFrame : startFrame);
if (looping && !finished && transitionframe != currentFrame) {
#ifdef QTIMELINE_DEBUG
- qDebug() << "QTimeLinePrivate::setCurrentTime: transitionframe";
+ qDebug("QTimeLinePrivate::setCurrentTime: transitionframe");
#endif
emit q->frameChanged(transitionframe, QTimeLine::QPrivateSignal());
}
diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp
index 4672248945..3c7417d64e 100644
--- a/src/corelib/tools/qtimezone.cpp
+++ b/src/corelib/tools/qtimezone.cpp
@@ -67,7 +67,7 @@ static QTimeZonePrivate *newBackendTimeZone()
#elif defined Q_OS_UNIX
return new QTzTimeZonePrivate();
// Registry based timezone backend not available on WinRT
-#elif defined Q_OS_WIN && !defined Q_OS_WINRT
+#elif defined Q_OS_WIN
return new QWinTimeZonePrivate();
#elif defined QT_USE_ICU
return new QIcuTimeZonePrivate();
@@ -94,7 +94,7 @@ static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId)
#elif defined Q_OS_UNIX
return new QTzTimeZonePrivate(ianaId);
// Registry based timezone backend not available on WinRT
-#elif defined Q_OS_WIN && !defined Q_OS_WINRT
+#elif defined Q_OS_WIN
return new QWinTimeZonePrivate(ianaId);
#elif defined QT_USE_ICU
return new QIcuTimeZonePrivate(ianaId);
diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/tools/qtimezoneprivate_win.cpp
index 1d19f01b4e..f84b66fa99 100644
--- a/src/corelib/tools/qtimezoneprivate_win.cpp
+++ b/src/corelib/tools/qtimezoneprivate_win.cpp
@@ -48,6 +48,10 @@
QT_BEGIN_NAMESPACE
+#ifndef Q_OS_WINRT
+#define QT_USE_REGISTRY_TIMEZONE 1
+#endif
+
/*
Private
@@ -65,9 +69,10 @@ QT_BEGIN_NAMESPACE
// Vista introduced support for historic data, see MSDN docs on DYNAMIC_TIME_ZONE_INFORMATION
// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms724253%28v=vs.85%29.aspx
-
+#ifdef QT_USE_REGISTRY_TIMEZONE
static const char tzRegPath[] = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones";
static const char currTzRegPath[] = "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
+#endif
enum {
MIN_YEAR = -292275056,
@@ -129,6 +134,7 @@ static bool equalTzi(const TIME_ZONE_INFORMATION &tzi1, const TIME_ZONE_INFORMAT
&& wcscmp(tzi1.DaylightName, tzi2.DaylightName) == 0);
}
+#ifdef QT_USE_REGISTRY_TIMEZONE
static bool openRegistryKey(const QString &keyPath, HKEY *key)
{
return (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (const wchar_t*)keyPath.utf16(), 0, KEY_READ, key)
@@ -203,9 +209,61 @@ static TIME_ZONE_INFORMATION getRegistryTzi(const QByteArray &windowsId, bool *o
return tzi;
}
+#else // QT_USE_REGISTRY_TIMEZONE
+struct QWinDynamicTimeZone
+{
+ QString standardName;
+ QString daylightName;
+ QString timezoneName;
+ qint32 bias;
+ bool daylightTime;
+};
+
+typedef QHash<QByteArray, QWinDynamicTimeZone> QWinRTTimeZoneHash;
+
+Q_GLOBAL_STATIC(QWinRTTimeZoneHash, gTimeZones)
+
+static void enumerateTimeZones()
+{
+ DYNAMIC_TIME_ZONE_INFORMATION dtzInfo;
+ quint32 index = 0;
+ QString prevTimeZoneKeyName;
+ while (SUCCEEDED(EnumDynamicTimeZoneInformation(index++, &dtzInfo))) {
+ QWinDynamicTimeZone item;
+ item.timezoneName = QString::fromWCharArray(dtzInfo.TimeZoneKeyName);
+ // As soon as key name repeats, break. Some systems continue to always
+ // return the last item independent of index being out of range
+ if (item.timezoneName == prevTimeZoneKeyName)
+ break;
+ item.standardName = QString::fromWCharArray(dtzInfo.StandardName);
+ item.daylightName = QString::fromWCharArray(dtzInfo.DaylightName);
+ item.daylightTime = !dtzInfo.DynamicDaylightTimeDisabled;
+ item.bias = dtzInfo.Bias;
+ gTimeZones->insert(item.timezoneName.toUtf8(), item);
+ prevTimeZoneKeyName = item.timezoneName;
+ }
+}
+
+static DYNAMIC_TIME_ZONE_INFORMATION dynamicInfoForId(const QByteArray &windowsId)
+{
+ DYNAMIC_TIME_ZONE_INFORMATION dtzInfo;
+ quint32 index = 0;
+ QString prevTimeZoneKeyName;
+ while (SUCCEEDED(EnumDynamicTimeZoneInformation(index++, &dtzInfo))) {
+ const QString timeZoneName = QString::fromWCharArray(dtzInfo.TimeZoneKeyName);
+ if (timeZoneName == QLatin1String(windowsId))
+ break;
+ if (timeZoneName == prevTimeZoneKeyName)
+ break;
+ prevTimeZoneKeyName = timeZoneName;
+ }
+ return dtzInfo;
+}
+#endif // QT_USE_REGISTRY_TIMEZONE
static QList<QByteArray> availableWindowsIds()
{
+#ifdef QT_USE_REGISTRY_TIMEZONE
// TODO Consider caching results in a global static, very unlikely to change.
QList<QByteArray> list;
HKEY key = NULL;
@@ -223,10 +281,16 @@ static QList<QByteArray> availableWindowsIds()
RegCloseKey(key);
}
return list;
+#else // QT_USE_REGISTRY_TIMEZONE
+ if (gTimeZones->isEmpty())
+ enumerateTimeZones();
+ return gTimeZones->keys();
+#endif // QT_USE_REGISTRY_TIMEZONE
}
static QByteArray windowsSystemZoneId()
{
+#ifdef QT_USE_REGISTRY_TIMEZONE
// On Vista and later is held in the value TimeZoneKeyName in key currTzRegPath
QString id;
HKEY key = NULL;
@@ -248,6 +312,11 @@ static QByteArray windowsSystemZoneId()
if (equalTzi(getRegistryTzi(winId, &ok), sysTzi))
return winId;
}
+#else // QT_USE_REGISTRY_TIMEZONE
+ DYNAMIC_TIME_ZONE_INFORMATION dtzi;
+ if (SUCCEEDED(GetDynamicTimeZoneInformation(&dtzi)))
+ return QString::fromWCharArray(dtzi.TimeZoneKeyName).toLocal8Bit();
+#endif // QT_USE_REGISTRY_TIMEZONE
// If we can't determine the current ID use UTC
return QTimeZonePrivate::utcQByteArray();
@@ -368,6 +437,7 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
}
if (!m_windowsId.isEmpty()) {
+#ifdef QT_USE_REGISTRY_TIMEZONE
// Open the base TZI for the time zone
HKEY baseKey = NULL;
const QString baseKeyPath = QString::fromUtf8(tzRegPath) + QLatin1Char('\\')
@@ -404,6 +474,34 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
}
RegCloseKey(baseKey);
}
+#else // QT_USE_REGISTRY_TIMEZONE
+ if (gTimeZones->isEmpty())
+ enumerateTimeZones();
+ QWinRTTimeZoneHash::const_iterator it = gTimeZones->find(m_windowsId);
+ if (it != gTimeZones->constEnd()) {
+ m_displayName = it->timezoneName;
+ m_standardName = it->standardName;
+ m_daylightName = it->daylightName;
+ DWORD firstYear = 0;
+ DWORD lastYear = 0;
+ DYNAMIC_TIME_ZONE_INFORMATION dtzi = dynamicInfoForId(m_windowsId);
+ GetDynamicTimeZoneInformationEffectiveYears(&dtzi, &firstYear, &lastYear);
+ // If there is no dynamic information, you can still query for
+ // year 0, which helps simplifying following part
+ for (DWORD year = firstYear; year <= lastYear; ++year) {
+ TIME_ZONE_INFORMATION tzi;
+ if (!GetTimeZoneInformationForYear(year, &dtzi, &tzi))
+ continue;
+ QWinTransitionRule rule;
+ rule.standardTimeBias = tzi.Bias + tzi.StandardBias;
+ rule.daylightTimeBias = tzi.Bias + tzi.DaylightBias - rule.standardTimeBias;
+ rule.standardTimeRule = tzi.StandardDate;
+ rule.daylightTimeRule = tzi.DaylightDate;
+ rule.startYear = year;
+ m_tranRules.append(rule);
+ }
+ }
+#endif // QT_USE_REGISTRY_TIMEZONE
}
// If there are no rules then we failed to find a windowsId or any tzi info
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index b87f234f40..95a7ece67c 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -144,9 +144,11 @@ else:unix {
SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp tools/qtimezoneprivate_tz.cpp
}
else:win32 {
- SOURCES += tools/qelapsedtimer_win.cpp tools/qlocale_win.cpp
- !winrt: SOURCES += tools/qtimezoneprivate_win.cpp
+ SOURCES += tools/qelapsedtimer_win.cpp \
+ tools/qlocale_win.cpp \
+ tools/qtimezoneprivate_win.cpp
winphone: LIBS_PRIVATE += -lWindowsPhoneGlobalizationUtil
+ winrt-*-msvc2013: LIBS += advapi32.lib
} else:integrity:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp
else:SOURCES += tools/qelapsedtimer_generic.cpp
@@ -204,7 +206,7 @@ contains(QT_CONFIG, doubleconversion) {
}
# Note: libm should be present by default becaue this is C++
-!macx-icc:!vxworks:!haiku:unix:LIBS_PRIVATE += -lm
+unix:!macx-icc:!vxworks:!haiku:!integrity: LIBS_PRIVATE += -lm
TR_EXCLUDE += ../3rdparty/*