summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2018-06-07 19:10:53 +0200
committerLiang Qi <liang.qi@qt.io>2018-06-07 19:10:53 +0200
commit096e37910d93f9c52976600e985c615ea36fe291 (patch)
tree713d020f4a04f03d8ca6e111055e7eebe85953a8 /src/corelib
parent88eda007a3b5046999dd0b287634765efcd8934d (diff)
parenta14a943f9ac3d1e85514d7fb6688c84e624ac850 (diff)
Merge remote-tracking branch 'origin/5.11' into dev
Conflicts: .qmake.conf src/corelib/kernel/qeventdispatcher_cf.mm src/gui/kernel/qguiapplication_p.h src/gui/kernel/qwindowsysteminterface.cpp src/gui/kernel/qwindowsysteminterface.h src/plugins/platforms/cocoa/qcocoawindow.mm src/plugins/platforms/cocoa/qnswindowdelegate.mm src/plugins/platforms/ios/qioseventdispatcher.mm src/plugins/platforms/windows/qwindowsdrag.h src/plugins/platforms/windows/qwindowsinternalmimedata.h src/plugins/platforms/windows/qwindowsmime.cpp src/plugins/platforms/winrt/qwinrtscreen.cpp Change-Id: Ic817f265c2386e83839d2bb9ef7419cb29705246
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/global/qglobal.cpp12
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents.mm2
-rw-r--r--src/corelib/io/qprocess_unix.cpp2
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm28
-rw-r--r--src/corelib/kernel/qcore_mac_p.h14
-rw-r--r--src/corelib/kernel/qeventdispatcher_cf.mm17
-rw-r--r--src/corelib/mimetypes/qmimemagicrule.cpp16
-rw-r--r--src/corelib/thread/qatomic_msvc.h485
-rw-r--r--src/corelib/thread/qbasicatomic.h14
-rw-r--r--src/corelib/thread/qthread.cpp19
-rw-r--r--src/corelib/thread/thread.pri2
-rw-r--r--src/corelib/tools/qlocale_unix.cpp20
-rw-r--r--src/corelib/tools/qpoint.h12
13 files changed, 598 insertions, 45 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index ea62c8247a..b654f5863a 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -940,6 +940,8 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value));
Rounds \a d to the nearest integer.
+ Rounds half up (e.g. 0.5 -> 1, -0.5 -> 0).
+
Example:
\snippet code/src_corelib_global_qglobal.cpp 11A
@@ -950,6 +952,8 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value));
Rounds \a d to the nearest integer.
+ Rounds half up (e.g. 0.5f -> 1, -0.5f -> 0).
+
Example:
\snippet code/src_corelib_global_qglobal.cpp 11B
@@ -960,6 +964,8 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value));
Rounds \a d to the nearest 64-bit integer.
+ Rounds half up (e.g. 0.5 -> 1, -0.5 -> 0).
+
Example:
\snippet code/src_corelib_global_qglobal.cpp 12A
@@ -970,6 +976,8 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value));
Rounds \a d to the nearest 64-bit integer.
+ Rounds half up (e.g. 0.5f -> 1, -0.5f -> 0).
+
Example:
\snippet code/src_corelib_global_qglobal.cpp 12B
@@ -4048,7 +4056,7 @@ Q_GLOBAL_STATIC(QInternal_CallBackTable, global_callback_table)
bool QInternal::registerCallback(Callback cb, qInternalCallback callback)
{
- if (cb >= 0 && cb < QInternal::LastCallback) {
+ if (unsigned(cb) < unsigned(QInternal::LastCallback)) {
QInternal_CallBackTable *cbt = global_callback_table();
cbt->callbacks.resize(cb + 1);
cbt->callbacks[cb].append(callback);
@@ -4059,7 +4067,7 @@ bool QInternal::registerCallback(Callback cb, qInternalCallback callback)
bool QInternal::unregisterCallback(Callback cb, qInternalCallback callback)
{
- if (cb >= 0 && cb < QInternal::LastCallback) {
+ if (unsigned(cb) < unsigned(QInternal::LastCallback)) {
if (global_callback_table.exists()) {
QInternal_CallBackTable *cbt = global_callback_table();
return (bool) cbt->callbacks[cb].removeAll(callback);
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.mm b/src/corelib/io/qfilesystemwatcher_fsevents.mm
index 844aa9daa7..f68fb67d79 100644
--- a/src/corelib/io/qfilesystemwatcher_fsevents.mm
+++ b/src/corelib/io/qfilesystemwatcher_fsevents.mm
@@ -377,7 +377,7 @@ QStringList QFseventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
for (PathRefCounts::const_iterator i = watchingState.watchedPaths.begin(),
ei = watchingState.watchedPaths.end(); i != ei; ++i) {
- if (watchedPath.startsWith(i.key())) {
+ if (watchedPath.startsWith(i.key() % QDir::separator())) {
watchedPath = i.key();
break;
}
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 68b7a8bf9b..a849519635 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -925,6 +925,8 @@ bool QProcessPrivate::startDetached(qint64 *pid)
closeChannel(&stdinChannel);
closeChannel(&stdoutChannel);
closeChannel(&stderrChannel);
+ qt_safe_close(pidPipe[0]);
+ qt_safe_close(pidPipe[1]);
qt_safe_close(startedPipe[0]);
qt_safe_close(startedPipe[1]);
return false;
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index c1062e98b8..97a3acacd2 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -162,6 +162,34 @@ QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool)
}
#endif // !QT_NO_DEBUG_STREAM
+bool qt_apple_isApplicationExtension()
+{
+ static bool isExtension = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSExtension"];
+ return isExtension;
+}
+
+#if !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WATCHOS)
+AppleApplication *qt_apple_sharedApplication()
+{
+ // Application extensions are not allowed to access the shared application
+ if (qt_apple_isApplicationExtension()) {
+ qWarning() << "accessing the shared" << [AppleApplication class]
+ << "is not allowed in application extensions";
+
+ // In practice the application is actually available, but the the App
+ // review process will likely catch uses of it, so we return nil just
+ // in case, unless we don't care about being App Store compliant.
+#if QT_CONFIG(appstore_compliant)
+ return nil;
+#endif
+ }
+
+ // We use performSelector so that building with -fapplication-extension will
+ // not mistakenly think we're using the shared application in extensions.
+ return [[AppleApplication class] performSelector:@selector(sharedApplication)];
+}
+#endif
+
#ifdef Q_OS_MACOS
/*
Ensure that Objective-C objects auto-released in main(), directly or indirectly,
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index e8aa24b944..84978bbbc3 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -190,6 +190,20 @@ QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
#endif
Q_CORE_EXPORT void qt_apple_check_os_version();
+Q_CORE_EXPORT bool qt_apple_isApplicationExtension();
+
+#if !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WATCHOS)
+QT_END_NAMESPACE
+# if defined(Q_OS_MACOS)
+Q_FORWARD_DECLARE_OBJC_CLASS(NSApplication);
+using AppleApplication = NSApplication;
+# else
+Q_FORWARD_DECLARE_OBJC_CLASS(UIApplication);
+using AppleApplication = UIApplication;
+# endif
+QT_BEGIN_NAMESPACE
+Q_CORE_EXPORT AppleApplication *qt_apple_sharedApplication();
+#endif
// --------------------------------------------------------------------------
diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm
index a6c5ccd7a8..73eeaba03f 100644
--- a/src/corelib/kernel/qeventdispatcher_cf.mm
+++ b/src/corelib/kernel/qeventdispatcher_cf.mm
@@ -90,17 +90,12 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(RunLoopModeTracker);
if ((self = [super init])) {
m_runLoopModes.push(kCFRunLoopDefaultMode);
- [[NSNotificationCenter defaultCenter]
- addObserver:self
- selector:@selector(receivedNotification:)
- name:nil
-#ifdef Q_OS_OSX
- object:NSApplication.sharedApplication];
-#elif defined(Q_OS_WATCHOS)
- object:WKExtension.sharedExtension];
-#else
- // Use performSelector so this can work in an App Extension
- object:[UIApplication.class performSelector:@selector(sharedApplication)]];
+#if !defined(Q_OS_WATCHOS)
+ if (!qt_apple_isApplicationExtension()) {
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self selector:@selector(receivedNotification:)
+ name:nil object:qt_apple_sharedApplication()];
+ }
#endif
}
diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp
index 6356a3581b..9dadebc999 100644
--- a/src/corelib/mimetypes/qmimemagicrule.cpp
+++ b/src/corelib/mimetypes/qmimemagicrule.cpp
@@ -315,18 +315,14 @@ QMimeMagicRule::QMimeMagicRule(const QString &type,
break;
case Big32:
case Little32:
- if (m_number <= quint32(-1)) {
- m_number = m_type == Little32 ? qFromLittleEndian<quint32>(m_number) : qFromBigEndian<quint32>(m_number);
- if (m_numberMask != 0)
- m_numberMask = m_type == Little32 ? qFromLittleEndian<quint32>(m_numberMask) : qFromBigEndian<quint32>(m_numberMask);
- }
+ m_number = m_type == Little32 ? qFromLittleEndian<quint32>(m_number) : qFromBigEndian<quint32>(m_number);
+ if (m_numberMask != 0)
+ m_numberMask = m_type == Little32 ? qFromLittleEndian<quint32>(m_numberMask) : qFromBigEndian<quint32>(m_numberMask);
Q_FALLTHROUGH();
case Host32:
- if (m_number <= quint32(-1)) {
- if (m_numberMask == 0)
- m_numberMask = quint32(-1);
- m_matchFunction = &QMimeMagicRule::matchNumber<quint32>;
- }
+ if (m_numberMask == 0)
+ m_numberMask = quint32(-1);
+ m_matchFunction = &QMimeMagicRule::matchNumber<quint32>;
break;
default:
break;
diff --git a/src/corelib/thread/qatomic_msvc.h b/src/corelib/thread/qatomic_msvc.h
new file mode 100644
index 0000000000..5eae2bdc48
--- /dev/null
+++ b/src/corelib/thread/qatomic_msvc.h
@@ -0,0 +1,485 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_MSVC_H
+#define QATOMIC_MSVC_H
+
+#include <QtCore/qgenericatomic.h>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// use compiler intrinsics for all atomic functions
+# define QT_INTERLOCKED_PREFIX _
+# define QT_INTERLOCKED_PROTOTYPE
+# define QT_INTERLOCKED_DECLARE_PROTOTYPES
+# define QT_INTERLOCKED_INTRINSIC
+# define Q_ATOMIC_INT16_IS_SUPPORTED
+
+# ifdef _WIN64
+# define Q_ATOMIC_INT64_IS_SUPPORTED
+# endif
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Prototype declaration
+
+#define QT_INTERLOCKED_CONCAT_I(prefix, suffix) \
+ prefix ## suffix
+#define QT_INTERLOCKED_CONCAT(prefix, suffix) \
+ QT_INTERLOCKED_CONCAT_I(prefix, suffix)
+
+// MSVC intrinsics prefix function names with an underscore. Also, if platform
+// SDK headers have been included, the Interlocked names may be defined as
+// macros.
+// To avoid double underscores, we paste the prefix with Interlocked first and
+// then the remainder of the function name.
+#define QT_INTERLOCKED_FUNCTION(name) \
+ QT_INTERLOCKED_CONCAT( \
+ QT_INTERLOCKED_CONCAT(QT_INTERLOCKED_PREFIX, Interlocked), name)
+
+#ifndef QT_INTERLOCKED_VOLATILE
+# define QT_INTERLOCKED_VOLATILE volatile
+#endif
+
+#ifndef QT_INTERLOCKED_PREFIX
+#define QT_INTERLOCKED_PREFIX
+#endif
+
+#ifndef QT_INTERLOCKED_PROTOTYPE
+#define QT_INTERLOCKED_PROTOTYPE
+#endif
+
+#ifdef QT_INTERLOCKED_DECLARE_PROTOTYPES
+#undef QT_INTERLOCKED_DECLARE_PROTOTYPES
+
+extern "C" {
+
+ long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Increment )(long QT_INTERLOCKED_VOLATILE *);
+ long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Decrement )(long QT_INTERLOCKED_VOLATILE *);
+ long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( CompareExchange )(long QT_INTERLOCKED_VOLATILE *, long, long);
+ long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Exchange )(long QT_INTERLOCKED_VOLATILE *, long);
+ long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( ExchangeAdd )(long QT_INTERLOCKED_VOLATILE *, long);
+
+# if !defined(__i386__) && !defined(_M_IX86)
+ void * QT_INTERLOCKED_FUNCTION( CompareExchangePointer )(void * QT_INTERLOCKED_VOLATILE *, void *, void *);
+ void * QT_INTERLOCKED_FUNCTION( ExchangePointer )(void * QT_INTERLOCKED_VOLATILE *, void *);
+ __int64 QT_INTERLOCKED_FUNCTION( ExchangeAdd64 )(__int64 QT_INTERLOCKED_VOLATILE *, __int64);
+# endif
+
+# ifdef Q_ATOMIC_INT16_IS_SUPPORTED
+ short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Increment16 )(short QT_INTERLOCKED_VOLATILE *);
+ short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Decrement16 )(short QT_INTERLOCKED_VOLATILE *);
+ short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( CompareExchange16 )(short QT_INTERLOCKED_VOLATILE *, short, short);
+ short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Exchange16 )(short QT_INTERLOCKED_VOLATILE *, short);
+ short QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( ExchangeAdd16 )(short QT_INTERLOCKED_VOLATILE *, short);
+# endif
+# ifdef Q_ATOMIC_INT64_IS_SUPPORTED
+ __int64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Increment64 )(__int64 QT_INTERLOCKED_VOLATILE *);
+ __int64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Decrement64 )(__int64 QT_INTERLOCKED_VOLATILE *);
+ __int64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( CompareExchange64 )(__int64 QT_INTERLOCKED_VOLATILE *, __int64, __int64);
+ __int64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Exchange64 )(__int64 QT_INTERLOCKED_VOLATILE *, __int64);
+ //above already: qint64 QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( ExchangeAdd64 )(qint64 QT_INTERLOCKED_VOLATILE *, qint64);
+# endif
+}
+
+#endif // QT_INTERLOCKED_DECLARE_PROTOTYPES
+
+#undef QT_INTERLOCKED_PROTOTYPE
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef QT_INTERLOCKED_INTRINSIC
+#undef QT_INTERLOCKED_INTRINSIC
+
+# pragma intrinsic (_InterlockedIncrement)
+# pragma intrinsic (_InterlockedDecrement)
+# pragma intrinsic (_InterlockedExchange)
+# pragma intrinsic (_InterlockedCompareExchange)
+# pragma intrinsic (_InterlockedExchangeAdd)
+
+# if !defined(_M_IX86)
+# pragma intrinsic (_InterlockedCompareExchangePointer)
+# pragma intrinsic (_InterlockedExchangePointer)
+# pragma intrinsic (_InterlockedExchangeAdd64)
+# endif
+
+#endif // QT_INTERLOCKED_INTRINSIC
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interlocked* replacement macros
+
+#if defined(__i386__) || defined(_M_IX86)
+
+# define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \
+ reinterpret_cast<void *>( \
+ QT_INTERLOCKED_FUNCTION(CompareExchange)( \
+ reinterpret_cast<long QT_INTERLOCKED_VOLATILE *>(value), \
+ long(newValue), \
+ long(expectedValue)))
+
+# define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \
+ QT_INTERLOCKED_FUNCTION(Exchange)( \
+ reinterpret_cast<long QT_INTERLOCKED_VOLATILE *>(value), \
+ long(newValue))
+
+# define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \
+ QT_INTERLOCKED_FUNCTION(ExchangeAdd)( \
+ reinterpret_cast<long QT_INTERLOCKED_VOLATILE *>(value), \
+ (valueToAdd))
+
+#else // !defined(__i386__) && !defined(_M_IX86)
+
+# define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \
+ QT_INTERLOCKED_FUNCTION(CompareExchangePointer)( \
+ (void * QT_INTERLOCKED_VOLATILE *)(value), \
+ (void *) (newValue), \
+ (void *) (expectedValue))
+
+# define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \
+ QT_INTERLOCKED_FUNCTION(ExchangePointer)( \
+ (void * QT_INTERLOCKED_VOLATILE *)(value), \
+ (void *) (newValue))
+
+# define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \
+ QT_INTERLOCKED_FUNCTION(ExchangeAdd64)( \
+ reinterpret_cast<qint64 QT_INTERLOCKED_VOLATILE *>(value), \
+ (valueToAdd))
+
+#endif // !defined(__i386__) && !defined(_M_IX86)
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QT_BEGIN_NAMESPACE
+
+#if 0
+// silence syncqt warnings
+QT_END_NAMESPACE
+#pragma qt_sync_skip_header_check
+#pragma qt_sync_stop_processing
+#endif
+
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE
+
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE
+
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE
+
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE
+
+#define Q_ATOMIC_INT32_IS_SUPPORTED
+
+#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_WAIT_FREE
+
+#define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT32_TEST_AND_SET_IS_WAIT_FREE
+
+#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_WAIT_FREE
+
+#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_WAIT_FREE
+
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE
+
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE
+
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE
+
+#ifdef Q_ATOMIC_INT16_IS_SUPPORTED
+# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_WAIT_FREE
+
+# define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE
+# define Q_ATOMIC_INT16_TEST_AND_SET_IS_WAIT_FREE
+
+# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_WAIT_FREE
+
+# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_WAIT_FREE
+
+template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; };
+#endif
+
+#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
+# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_WAIT_FREE
+
+# define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE
+# define Q_ATOMIC_INT64_TEST_AND_SET_IS_WAIT_FREE
+
+# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_WAIT_FREE
+
+# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_WAIT_FREE
+
+template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; };
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <int N> struct QAtomicWindowsType { typedef typename QIntegerForSize<N>::Signed Type; };
+template <> struct QAtomicWindowsType<4> { typedef long Type; };
+
+
+template <int N> struct QAtomicOpsBySize : QGenericAtomicOps<QAtomicOpsBySize<N> >
+{
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return true; }
+ static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return true; }
+ template <typename T> static bool ref(T &_q_value) Q_DECL_NOTHROW;
+ template <typename T> static bool deref(T &_q_value) Q_DECL_NOTHROW;
+
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; }
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return true; }
+ template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW;
+ template <typename T>
+ static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW;
+
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return true; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return true; }
+ template <typename T> static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW;
+
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return true; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return true; }
+ template <typename T> static T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW;
+
+private:
+ typedef typename QAtomicWindowsType<N>::Type Type;
+ template <typename T> static inline Type *atomic(T *t)
+ { Q_STATIC_ASSERT(sizeof(T) == sizeof(Type)); return reinterpret_cast<Type *>(t); }
+ template <typename T> static inline Type value(T t)
+ { Q_STATIC_ASSERT(sizeof(T) == sizeof(Type)); return Type(t); }
+};
+
+template <typename T>
+struct QAtomicOps : QAtomicOpsBySize<sizeof(T)>
+{
+ typedef T Type;
+};
+
+template<> template<typename T>
+inline bool QAtomicOpsBySize<4>::ref(T &_q_value) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(Increment)(atomic(&_q_value)) != 0;
+}
+
+template<> template<typename T>
+inline bool QAtomicOpsBySize<4>::deref(T &_q_value) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(Decrement)(atomic(&_q_value)) != 0;
+}
+
+template<> template<typename T>
+inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(CompareExchange)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
+}
+
+template<> template <typename T>
+inline bool QAtomicOpsBySize<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
+{
+ *currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange)(atomic(&_q_value), newValue, expectedValue));
+ return *currentValue == expectedValue;
+}
+
+template<> template<typename T>
+inline T QAtomicOpsBySize<4>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(Exchange)(atomic(&_q_value), value(newValue));
+}
+
+template<> template<typename T>
+inline T QAtomicOpsBySize<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(ExchangeAdd)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
+}
+
+#ifdef Q_ATOMIC_INT16_IS_SUPPORTED
+template<> template<typename T>
+inline bool QAtomicOpsBySize<2>::ref(T &_q_value) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(Increment16)(atomic(&_q_value)) != 0;
+}
+
+template<> template<typename T>
+inline bool QAtomicOpsBySize<2>::deref(T &_q_value) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(Decrement16)(atomic(&_q_value)) != 0;
+}
+
+template<> template<typename T>
+inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(CompareExchange16)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
+}
+
+template<> template <typename T>
+inline bool QAtomicOpsBySize<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
+{
+ *currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange16)(atomic(&_q_value), newValue, expectedValue));
+ return *currentValue == expectedValue;
+}
+
+template<> template<typename T>
+inline T QAtomicOpsBySize<2>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(Exchange16)(atomic(&_q_value), value(newValue));
+}
+
+template<> template<typename T>
+inline T QAtomicOpsBySize<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(ExchangeAdd16)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
+}
+#endif
+
+#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
+template<> template<typename T>
+inline bool QAtomicOpsBySize<8>::ref(T &_q_value) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(Increment64)(atomic(&_q_value)) != 0;
+}
+
+template<> template<typename T>
+inline bool QAtomicOpsBySize<8>::deref(T &_q_value) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(Decrement64)(atomic(&_q_value)) != 0;
+}
+
+template<> template<typename T>
+inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(CompareExchange64)(atomic(&_q_value), value(newValue), value(expectedValue)) == value(expectedValue);
+}
+
+template<> template <typename T>
+inline bool QAtomicOpsBySize<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
+{
+ *currentValue = T(QT_INTERLOCKED_FUNCTION(CompareExchange64)(atomic(&_q_value), newValue, expectedValue));
+ return *currentValue == expectedValue;
+}
+
+template<> template<typename T>
+inline T QAtomicOpsBySize<8>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(Exchange64)(atomic(&_q_value), value(newValue));
+}
+
+template<> template<typename T>
+inline T QAtomicOpsBySize<8>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_FUNCTION(ExchangeAdd64)(atomic(&_q_value), value<T>(valueToAdd * QAtomicAdditiveType<T>::AddScale));
+}
+#endif
+
+// Specialization for pointer types, since we have Interlocked*Pointer() variants in some configurations
+template <typename T>
+struct QAtomicOps<T *> : QGenericAtomicOps<QAtomicOps<T *> >
+{
+ typedef T *Type;
+
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; }
+ static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return true; }
+ static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) Q_DECL_NOTHROW;
+ static bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) Q_DECL_NOTHROW;
+
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return true; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return true; }
+ static T *fetchAndStoreRelaxed(T *&_q_value, T *newValue) Q_DECL_NOTHROW;
+
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return true; }
+ static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return true; }
+ static T *fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) Q_DECL_NOTHROW;
+};
+
+template <typename T>
+inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) Q_DECL_NOTHROW
+{
+ return QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue) == expectedValue;
+}
+
+template <typename T>
+inline bool QAtomicOps<T *>::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) Q_DECL_NOTHROW
+{
+ *currentValue = reinterpret_cast<T *>(QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue));
+ return *currentValue == expectedValue;
+}
+
+template <typename T>
+inline T *QAtomicOps<T *>::fetchAndStoreRelaxed(T *&_q_value, T *newValue) Q_DECL_NOTHROW
+{
+ return reinterpret_cast<T *>(QT_INTERLOCKED_EXCHANGE_POINTER(&_q_value, newValue));
+}
+
+template <typename T>
+inline T *QAtomicOps<T *>::fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) Q_DECL_NOTHROW
+{
+ return reinterpret_cast<T *>(QT_INTERLOCKED_EXCHANGE_ADD_POINTER(&_q_value, valueToAdd * sizeof(T)));
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Cleanup
+
+#undef QT_INTERLOCKED_CONCAT_I
+#undef QT_INTERLOCKED_CONCAT
+#undef QT_INTERLOCKED_FUNCTION
+#undef QT_INTERLOCKED_PREFIX
+
+#undef QT_INTERLOCKED_VOLATILE
+
+#undef QT_INTERLOCKED_INCREMENT
+#undef QT_INTERLOCKED_DECREMENT
+#undef QT_INTERLOCKED_COMPARE_EXCHANGE
+#undef QT_INTERLOCKED_EXCHANGE
+#undef QT_INTERLOCKED_EXCHANGE_ADD
+#undef QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER
+#undef QT_INTERLOCKED_EXCHANGE_POINTER
+#undef QT_INTERLOCKED_EXCHANGE_ADD_POINTER
+
+QT_END_NAMESPACE
+#endif // QATOMIC_MSVC_H
diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h
index aacd12f220..a0304697b8 100644
--- a/src/corelib/thread/qbasicatomic.h
+++ b/src/corelib/thread/qbasicatomic.h
@@ -45,8 +45,20 @@
#if defined(QT_BOOTSTRAPPED)
# include <QtCore/qatomic_bootstrap.h>
-#else
+
+// If C++11 atomics are supported, use them!
+// Note that constexpr support is sometimes disabled in QNX builds but its
+// library has <atomic>.
+#elif defined(Q_COMPILER_ATOMICS) && (defined(Q_COMPILER_CONSTEXPR) || defined(Q_OS_QNX))
# include <QtCore/qatomic_cxx11.h>
+
+// We only support one fallback: MSVC, because even on version 2015, it lacks full constexpr support
+#elif defined(Q_CC_MSVC)
+# include <QtCore/qatomic_msvc.h>
+
+// No fallback
+#else
+# error "Qt requires C++11 support"
#endif
QT_WARNING_PUSH
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index 7d908fd4e7..23606411ff 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -219,14 +219,17 @@ QThreadPrivate::~QThreadPrivate()
It is important to remember that a QThread instance \l{QObject#Thread
Affinity}{lives in} the old thread that instantiated it, not in the
new thread that calls run(). This means that all of QThread's queued
- slots will execute in the old thread. Thus, a developer who wishes to
- invoke slots in the new thread must use the worker-object approach; new
- slots should not be implemented directly into a subclassed QThread.
-
- When subclassing QThread, keep in mind that the constructor executes in
- the old thread while run() executes in the new thread. If a member
- variable is accessed from both functions, then the variable is accessed
- from two different threads. Check that it is safe to do so.
+ slots and \l {QMetaObject::invokeMethod()}{invoked methods} will execute
+ in the old thread. Thus, a developer who wishes to invoke slots in the
+ new thread must use the worker-object approach; new slots should not be
+ implemented directly into a subclassed QThread.
+
+ Unlike queued slots or invoked methods, methods called directly on the
+ QThread object will execute in the thread that calls the method. When
+ subclassing QThread, keep in mind that the constructor executes in the
+ old thread while run() executes in the new thread. If a member variable
+ is accessed from both functions, then the variable is accessed from two
+ different threads. Check that it is safe to do so.
\note Care must be taken when interacting with objects across different
threads. See \l{Synchronizing Threads} for details.
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
index 47775f3fde..dae72564b4 100644
--- a/src/corelib/thread/thread.pri
+++ b/src/corelib/thread/thread.pri
@@ -53,6 +53,8 @@ qtConfig(future) {
}
win32 {
+ HEADERS += thread/qatomic_msvc.h
+
SOURCES += \
thread/qmutex_win.cpp \
thread/qthread_win.cpp \
diff --git a/src/corelib/tools/qlocale_unix.cpp b/src/corelib/tools/qlocale_unix.cpp
index 1a9184bca9..f202082213 100644
--- a/src/corelib/tools/qlocale_unix.cpp
+++ b/src/corelib/tools/qlocale_unix.cpp
@@ -107,7 +107,7 @@ Q_GLOBAL_STATIC(QSystemLocaleData, qSystemLocaleData)
#ifndef QT_NO_SYSTEMLOCALE
-static bool contradicts(const QByteArray &maybe, const QByteArray &known)
+static bool contradicts(const QString &maybe, const QString &known)
{
if (maybe.isEmpty())
return false;
@@ -137,25 +137,25 @@ static bool contradicts(const QByteArray &maybe, const QByteArray &known)
QLocale QSystemLocale::fallbackUiLocale() const
{
// See man 7 locale for precedence - LC_ALL beats LC_MESSAGES beats LANG:
- QByteArray lang = qgetenv("LC_ALL");
+ QString lang = qEnvironmentVariable("LC_ALL");
if (lang.isEmpty())
- lang = qgetenv("LC_MESSAGES");
+ lang = qEnvironmentVariable("LC_MESSAGES");
if (lang.isEmpty())
- lang = qgetenv("LANG");
+ lang = qEnvironmentVariable("LANG");
// if the locale is the "C" locale, then we can return the language we found here:
- if (lang.isEmpty() || lang == QByteArray("C") || lang == QByteArray("POSIX"))
- return QLocale(QString::fromLatin1(lang));
+ if (lang.isEmpty() || lang == QLatin1String("C") || lang == QLatin1String("POSIX"))
+ return QLocale(lang);
// ... otherwise, if the first part of LANGUAGE says more than or
// contradicts what we have, use that:
- QByteArray language = qgetenv("LANGUAGE");
+ QString language = qEnvironmentVariable("LANGUAGE");
if (!language.isEmpty()) {
- language = language.split(':').constFirst();
+ language = language.split(QLatin1Char(':')).constFirst();
if (contradicts(language, lang))
- return QLocale(QString::fromLatin1(language));
+ return QLocale(language);
}
- return QLocale(QString::fromLatin1(lang));
+ return QLocale(lang);
}
QVariant QSystemLocale::query(QueryType type, QVariant in) const
diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h
index 0f3e0c3517..ae46f0d39f 100644
--- a/src/corelib/tools/qpoint.h
+++ b/src/corelib/tools/qpoint.h
@@ -345,16 +345,24 @@ Q_DECL_RELAXED_CONSTEXPR inline QPointF &QPointF::operator*=(qreal c)
xp*=c; yp*=c; return *this;
}
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
+QT_WARNING_DISABLE_GCC("-Wfloat-equal")
+
Q_DECL_CONSTEXPR inline bool operator==(const QPointF &p1, const QPointF &p2)
{
- return qFuzzyIsNull(p1.xp - p2.xp) && qFuzzyIsNull(p1.yp - p2.yp);
+ return ((!p1.xp && !p1.yp) || (!p2.xp && !p2.yp))
+ ? (qFuzzyIsNull(p1.xp - p2.xp) && qFuzzyIsNull(p1.yp - p2.yp))
+ : (qFuzzyCompare(p1.xp, p2.xp) && qFuzzyCompare(p1.yp, p2.yp));
}
Q_DECL_CONSTEXPR inline bool operator!=(const QPointF &p1, const QPointF &p2)
{
- return !qFuzzyIsNull(p1.xp - p2.xp) || !qFuzzyIsNull(p1.yp - p2.yp);
+ return !(p1 == p2);
}
+QT_WARNING_POP
+
Q_DECL_CONSTEXPR inline const QPointF operator+(const QPointF &p1, const QPointF &p2)
{
return QPointF(p1.xp+p2.xp, p1.yp+p2.yp);