diff options
author | Liang Qi <liang.qi@qt.io> | 2018-06-07 19:10:53 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2018-06-07 19:10:53 +0200 |
commit | 096e37910d93f9c52976600e985c615ea36fe291 (patch) | |
tree | 713d020f4a04f03d8ca6e111055e7eebe85953a8 /src/corelib | |
parent | 88eda007a3b5046999dd0b287634765efcd8934d (diff) | |
parent | a14a943f9ac3d1e85514d7fb6688c84e624ac850 (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.cpp | 12 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_fsevents.mm | 2 | ||||
-rw-r--r-- | src/corelib/io/qprocess_unix.cpp | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_mac_objc.mm | 28 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_mac_p.h | 14 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_cf.mm | 17 | ||||
-rw-r--r-- | src/corelib/mimetypes/qmimemagicrule.cpp | 16 | ||||
-rw-r--r-- | src/corelib/thread/qatomic_msvc.h | 485 | ||||
-rw-r--r-- | src/corelib/thread/qbasicatomic.h | 14 | ||||
-rw-r--r-- | src/corelib/thread/qthread.cpp | 19 | ||||
-rw-r--r-- | src/corelib/thread/thread.pri | 2 | ||||
-rw-r--r-- | src/corelib/tools/qlocale_unix.cpp | 20 | ||||
-rw-r--r-- | src/corelib/tools/qpoint.h | 12 |
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); |