From daa7f5375c58464bbe92744599f1e2258445e259 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 25 Feb 2018 17:41:11 -0800 Subject: q{,Utf8}Printable: avoid creating a copy of a QString MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have this QString() constructor call to permit things that convert to QString but aren't QString to be used in qPrintable, like a QStringBuilder-powered fast operator+ expression, like: qPrintable(string1 + ": " + string2) Unfortunately, it meant that we unnecessarily created a QString copy if the input was already QString. Change-Id: Iecab8770aa5840aba8edfffd1516bc94cec791a9 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Oswald Buddenhagen Reviewed-by: MÃ¥rten Nordheim Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.h | 5 +++-- src/corelib/tools/qstring.h | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 33885021ba..e31d4d9ad7 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -747,12 +747,13 @@ Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qSharedBuild() Q_DECL_NOTHROW; # define QT_DEBUG #endif +// QtPrivate::asString defined in qstring.h #ifndef qPrintable -# define qPrintable(string) QString(string).toLocal8Bit().constData() +# define qPrintable(string) QtPrivate::asString(string).toLocal8Bit().constData() #endif #ifndef qUtf8Printable -# define qUtf8Printable(string) QString(string).toUtf8().constData() +# define qUtf8Printable(string) QtPrivate::asString(string).toUtf8().constData() #endif /* diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 0138ae4098..b8f4d49831 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -1857,6 +1857,12 @@ QT_DEPRECATED inline QString escape(const QString &plain) { #endif } +namespace QtPrivate { +// used by qPrintable() and qUtf8Printable() macros +inline const QString &asString(const QString &s) { return s; } +inline QString &&asString(QString &&s) { return std::move(s); } +} + QT_END_NAMESPACE #if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER) -- cgit v1.2.3 From 38597dd08083f1f5cbf947cd3b0290065f2872c6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 10 Mar 2018 11:17:47 -0800 Subject: Atomic: silence MSVC warning in the generic fetchAndSub MSVC atomics still use the generic version, instead of qatomic_cxx11.h. The implementation of fetchAndSub is implemented on top of fetchAndAdd, but produced a warning with unsigned types. Change-Id: I72f5230ad59948f784eafffd151aa53435b75298 Reviewed-by: Lars Knoll --- src/corelib/thread/qgenericatomic.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/corelib') diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h index 5c4c02a2ec..89c4fe9a11 100644 --- a/src/corelib/thread/qgenericatomic.h +++ b/src/corelib/thread/qgenericatomic.h @@ -253,12 +253,15 @@ template struct QGenericAtomicOps return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd); } +QT_WARNING_PUSH +QT_WARNING_DISABLE_MSVC(4146) // unary minus operator applied to unsigned type, result still unsigned template static Q_ALWAYS_INLINE T fetchAndSubRelaxed(T &_q_value, typename QAtomicAdditiveType::AdditiveT operand) Q_DECL_NOTHROW { // implement fetchAndSub on top of fetchAndAdd return fetchAndAddRelaxed(_q_value, -operand); } +QT_WARNING_POP template static Q_ALWAYS_INLINE T fetchAndSubAcquire(T &_q_value, typename QAtomicAdditiveType::AdditiveT operand) Q_DECL_NOTHROW -- cgit v1.2.3 From 90493e16b8dd9edc6176d0abc255422edbbb05c3 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 18 Mar 2018 09:38:00 -0700 Subject: Atomics: remove qatomic_msvc.h No longer needed. The comment about missing constexpr support is incorrect: MSVC 2015 does have constexpr issues, but they don't affect our use of std::atomic. Change-Id: Ie9d9215342d449c48a11fffd151d11208137f00d Reviewed-by: Lars Knoll --- src/corelib/arch/arch.pri | 2 - src/corelib/arch/qatomic_msvc.h | 485 -------------------------------------- src/corelib/thread/qbasicatomic.h | 16 +- 3 files changed, 2 insertions(+), 501 deletions(-) delete mode 100644 src/corelib/arch/qatomic_msvc.h (limited to 'src/corelib') diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri index e490617c6b..c9e54d1972 100644 --- a/src/corelib/arch/arch.pri +++ b/src/corelib/arch/arch.pri @@ -1,5 +1,3 @@ -win32:HEADERS += arch/qatomic_msvc.h - HEADERS += \ arch/qatomic_bootstrap.h \ arch/qatomic_cxx11.h diff --git a/src/corelib/arch/qatomic_msvc.h b/src/corelib/arch/qatomic_msvc.h deleted file mode 100644 index 5eae2bdc48..0000000000 --- a/src/corelib/arch/qatomic_msvc.h +++ /dev/null @@ -1,485 +0,0 @@ -/**************************************************************************** -** -** 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 - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -// 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( \ - QT_INTERLOCKED_FUNCTION(CompareExchange)( \ - reinterpret_cast(value), \ - long(newValue), \ - long(expectedValue))) - -# define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \ - QT_INTERLOCKED_FUNCTION(Exchange)( \ - reinterpret_cast(value), \ - long(newValue)) - -# define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \ - QT_INTERLOCKED_FUNCTION(ExchangeAdd)( \ - reinterpret_cast(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(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 struct QAtomicWindowsType { typedef typename QIntegerForSize::Signed Type; }; -template <> struct QAtomicWindowsType<4> { typedef long Type; }; - - -template struct QAtomicOpsBySize : QGenericAtomicOps > -{ - 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 static bool ref(T &_q_value) Q_DECL_NOTHROW; - template 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 static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW; - template - 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 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 static T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW; - -private: - typedef typename QAtomicWindowsType::Type Type; - template static inline Type *atomic(T *t) - { Q_STATIC_ASSERT(sizeof(T) == sizeof(Type)); return reinterpret_cast(t); } - template static inline Type value(T t) - { Q_STATIC_ASSERT(sizeof(T) == sizeof(Type)); return Type(t); } -}; - -template -struct QAtomicOps : QAtomicOpsBySize -{ - typedef T Type; -}; - -template<> template -inline bool QAtomicOpsBySize<4>::ref(T &_q_value) Q_DECL_NOTHROW -{ - return QT_INTERLOCKED_FUNCTION(Increment)(atomic(&_q_value)) != 0; -} - -template<> template -inline bool QAtomicOpsBySize<4>::deref(T &_q_value) Q_DECL_NOTHROW -{ - return QT_INTERLOCKED_FUNCTION(Decrement)(atomic(&_q_value)) != 0; -} - -template<> template -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 -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 -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 -inline T QAtomicOpsBySize<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - return QT_INTERLOCKED_FUNCTION(ExchangeAdd)(atomic(&_q_value), value(valueToAdd * QAtomicAdditiveType::AddScale)); -} - -#ifdef Q_ATOMIC_INT16_IS_SUPPORTED -template<> template -inline bool QAtomicOpsBySize<2>::ref(T &_q_value) Q_DECL_NOTHROW -{ - return QT_INTERLOCKED_FUNCTION(Increment16)(atomic(&_q_value)) != 0; -} - -template<> template -inline bool QAtomicOpsBySize<2>::deref(T &_q_value) Q_DECL_NOTHROW -{ - return QT_INTERLOCKED_FUNCTION(Decrement16)(atomic(&_q_value)) != 0; -} - -template<> template -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 -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 -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 -inline T QAtomicOpsBySize<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - return QT_INTERLOCKED_FUNCTION(ExchangeAdd16)(atomic(&_q_value), value(valueToAdd * QAtomicAdditiveType::AddScale)); -} -#endif - -#ifdef Q_ATOMIC_INT64_IS_SUPPORTED -template<> template -inline bool QAtomicOpsBySize<8>::ref(T &_q_value) Q_DECL_NOTHROW -{ - return QT_INTERLOCKED_FUNCTION(Increment64)(atomic(&_q_value)) != 0; -} - -template<> template -inline bool QAtomicOpsBySize<8>::deref(T &_q_value) Q_DECL_NOTHROW -{ - return QT_INTERLOCKED_FUNCTION(Decrement64)(atomic(&_q_value)) != 0; -} - -template<> template -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 -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 -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 -inline T QAtomicOpsBySize<8>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - return QT_INTERLOCKED_FUNCTION(ExchangeAdd64)(atomic(&_q_value), value(valueToAdd * QAtomicAdditiveType::AddScale)); -} -#endif - -// Specialization for pointer types, since we have Interlocked*Pointer() variants in some configurations -template -struct QAtomicOps : QGenericAtomicOps > -{ - 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 -inline bool QAtomicOps::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) Q_DECL_NOTHROW -{ - return QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue) == expectedValue; -} - -template -inline bool QAtomicOps::testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue, T **currentValue) Q_DECL_NOTHROW -{ - *currentValue = reinterpret_cast(QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&_q_value, newValue, expectedValue)); - return *currentValue == expectedValue; -} - -template -inline T *QAtomicOps::fetchAndStoreRelaxed(T *&_q_value, T *newValue) Q_DECL_NOTHROW -{ - return reinterpret_cast(QT_INTERLOCKED_EXCHANGE_POINTER(&_q_value, newValue)); -} - -template -inline T *QAtomicOps::fetchAndAddRelaxed(T *&_q_value, qptrdiff valueToAdd) Q_DECL_NOTHROW -{ - return reinterpret_cast(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 92db7a6228..aacd12f220 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2011 Thiago Macieira -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2018 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -45,20 +45,8 @@ #if defined(QT_BOOTSTRAPPED) # include - -// If C++11 atomics are supported, use them! -// Note that constexpr support is sometimes disabled in QNX builds but its -// library has . -#elif defined(Q_COMPILER_ATOMICS) && (defined(Q_COMPILER_CONSTEXPR) || defined(Q_OS_QNX)) -# include - -// We only support one fallback: MSVC, because even on version 2015, it lacks full constexpr support -#elif defined(Q_CC_MSVC) -# include - -// No fallback #else -# error "Qt requires C++11 support" +# include #endif QT_WARNING_PUSH -- cgit v1.2.3 From 9fa2626ef8760fe2923af5b47d027e63d9333776 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 18 Mar 2018 09:40:01 -0700 Subject: Remove src/corelib/arch, merging with src/corelib/thread There is no more architecture-specific code. Change-Id: Ie9d9215342d449c48a11fffd151d11411cd73fc7 Reviewed-by: Lars Knoll --- src/corelib/arch/arch.pri | 5 - src/corelib/arch/qatomic_bootstrap.h | 97 ------- src/corelib/arch/qatomic_cxx11.h | 473 --------------------------------- src/corelib/corelib.pro | 1 - src/corelib/thread/qatomic_bootstrap.h | 97 +++++++ src/corelib/thread/qatomic_cxx11.h | 473 +++++++++++++++++++++++++++++++++ src/corelib/thread/thread.pri | 4 + 7 files changed, 574 insertions(+), 576 deletions(-) delete mode 100644 src/corelib/arch/arch.pri delete mode 100644 src/corelib/arch/qatomic_bootstrap.h delete mode 100644 src/corelib/arch/qatomic_cxx11.h create mode 100644 src/corelib/thread/qatomic_bootstrap.h create mode 100644 src/corelib/thread/qatomic_cxx11.h (limited to 'src/corelib') diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri deleted file mode 100644 index c9e54d1972..0000000000 --- a/src/corelib/arch/arch.pri +++ /dev/null @@ -1,5 +0,0 @@ -HEADERS += \ - arch/qatomic_bootstrap.h \ - arch/qatomic_cxx11.h - -qtConfig(std-atomic64): QMAKE_USE += libatomic diff --git a/src/corelib/arch/qatomic_bootstrap.h b/src/corelib/arch/qatomic_bootstrap.h deleted file mode 100644 index b463f817bd..0000000000 --- a/src/corelib/arch/qatomic_bootstrap.h +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2011 Thiago Macieira -** 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_BOOTSTRAP_H -#define QATOMIC_BOOTSTRAP_H - -#include - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -template struct QAtomicOps: QGenericAtomicOps > -{ - typedef T Type; - - static bool ref(T &_q_value) Q_DECL_NOTHROW - { - return ++_q_value != 0; - } - static bool deref(T &_q_value) Q_DECL_NOTHROW - { - return --_q_value != 0; - } - - static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW - { - if (currentValue) - *currentValue = _q_value; - if (_q_value == expectedValue) { - _q_value = newValue; - return true; - } - return false; - } - - static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW - { - T tmp = _q_value; - _q_value = newValue; - return tmp; - } - - template static - T fetchAndAddRelaxed(T &_q_value, AdditiveType valueToAdd) Q_DECL_NOTHROW - { - T returnValue = _q_value; - _q_value += valueToAdd; - return returnValue; - } -}; - -QT_END_NAMESPACE - -#endif // QATOMIC_BOOTSTRAP_H diff --git a/src/corelib/arch/qatomic_cxx11.h b/src/corelib/arch/qatomic_cxx11.h deleted file mode 100644 index 2fc0bf5419..0000000000 --- a/src/corelib/arch/qatomic_cxx11.h +++ /dev/null @@ -1,473 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Thiago Macieira -** 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_CXX11_H -#define QATOMIC_CXX11_H - -#include -#include - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -/* Attempt to detect whether the atomic operations exist in hardware - * or whether they are emulated by way of a lock. - * - * C++11 29.4 [atomics.lockfree] p1 says - * - * The ATOMIC_..._LOCK_FREE macros indicate the lock-free property of the - * corresponding atomic types, with the signed and unsigned variants grouped - * together. The properties also apply to the corresponding (partial) - * specializations of the atomic template. A value of 0 indicates that the - * types are never lock-free. A value of 1 indicates that the types are - * sometimes lock-free. A value of 2 indicates that the types are always - * lock-free. - * - * We have a problem when the value is 1: we'd need to check at runtime, but - * QAtomicInteger requires a constexpr answer (defect introduced in Qt 5.0). So - * we'll err in the side of caution and say it isn't. - */ - -// ### Qt 6: make non-constexpr (see above) -template struct QAtomicTraits -{ static Q_DECL_CONSTEXPR inline bool isLockFree(); }; - -#define Q_ATOMIC_INT32_IS_SUPPORTED -#if ATOMIC_INT_LOCK_FREE == 2 -# define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree() -{ return true; } -#elif ATOMIC_INT_LOCK_FREE == 1 -# define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT32_TEST_AND_SET_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_SOMETIMES_NATIVE - -template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree() -{ return false; } -#else -# define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NEVER_NATIVE -# define Q_ATOMIC_INT_TEST_AND_SET_IS_NEVER_NATIVE -# define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NEVER_NATIVE -# define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NEVER_NATIVE -# define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_NEVER_NATIVE -# define Q_ATOMIC_INT32_TEST_AND_SET_IS_NEVER_NATIVE -# define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_NEVER_NATIVE -# define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_NEVER_NATIVE - -template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree() -{ return false; } -#endif - -#if ATOMIC_POINTER_LOCK_FREE == 2 -# define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -# define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE -# define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE -# define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE -#elif ATOMIC_POINTER_LOCK_FREE == 1 -# define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE -#else -# define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_NEVER_NATIVE -# define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NEVER_NATIVE -# define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NEVER_NATIVE -# define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NEVER_NATIVE -#endif - -template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; }; -#define Q_ATOMIC_INT8_IS_SUPPORTED -#if ATOMIC_CHAR_LOCK_FREE == 2 -# define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT8_TEST_AND_SET_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree() -{ return true; } -#elif ATOMIC_CHAR_LOCK_FREE == 1 -# define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT8_TEST_AND_SET_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_SOMETIMES_NATIVE - -template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree() -{ return false; } -#else -# define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_NEVER_NATIVE -# define Q_ATOMIC_INT8_TEST_AND_SET_IS_NEVER_NATIVE -# define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_NEVER_NATIVE -# define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_NEVER_NATIVE - -template <> Q_DECL_CONSTEXPR bool QAtomicTraits<1>::isLockFree() -{ return false; } -#endif - -template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; }; -#define Q_ATOMIC_INT16_IS_SUPPORTED -#if ATOMIC_SHORT_LOCK_FREE == 2 -# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree() -{ return false; } -#elif ATOMIC_SHORT_LOCK_FREE == 1 -# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT16_TEST_AND_SET_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE - -template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree() -{ return false; } -#else -# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE -# define Q_ATOMIC_INT16_TEST_AND_SET_IS_NEVER_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE - -template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree() -{ return false; } -#endif - -#if QT_CONFIG(std_atomic64) -template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; -# define Q_ATOMIC_INT64_IS_SUPPORTED -# if ATOMIC_LLONG_LOCK_FREE == 2 -# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() -{ return true; } -# elif ATOMIC_LLONG_LOCK_FREE == 1 -# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT16_TEST_AND_SET_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE - -template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() -{ return false; } -# else -# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE -# define Q_ATOMIC_INT16_TEST_AND_SET_IS_NEVER_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE - -template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() -{ return false; } -# endif -#endif - -template struct QAtomicOps -{ - typedef std::atomic Type; - - template static inline - T load(const std::atomic &_q_value) Q_DECL_NOTHROW - { - return _q_value.load(std::memory_order_relaxed); - } - - template static inline - T load(const volatile std::atomic &_q_value) Q_DECL_NOTHROW - { - return _q_value.load(std::memory_order_relaxed); - } - - template static inline - T loadAcquire(const std::atomic &_q_value) Q_DECL_NOTHROW - { - return _q_value.load(std::memory_order_acquire); - } - - template static inline - T loadAcquire(const volatile std::atomic &_q_value) Q_DECL_NOTHROW - { - return _q_value.load(std::memory_order_acquire); - } - - template static inline - void store(std::atomic &_q_value, T newValue) Q_DECL_NOTHROW - { - _q_value.store(newValue, std::memory_order_relaxed); - } - - template static inline - void storeRelease(std::atomic &_q_value, T newValue) Q_DECL_NOTHROW - { - _q_value.store(newValue, std::memory_order_release); - } - - static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return isTestAndSetNative(); } - static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return false; } - template - static inline bool ref(std::atomic &_q_value) - { - return ++_q_value != 0; - } - - template - static inline bool deref(std::atomic &_q_value) Q_DECL_NOTHROW - { - return --_q_value != 0; - } - - static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW - { return QAtomicTraits::isLockFree(); } - static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; } - - template - static bool testAndSetRelaxed(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW - { - bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed); - if (currentValue) - *currentValue = expectedValue; - return tmp; - } - - template - static bool testAndSetAcquire(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW - { - bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acquire, std::memory_order_acquire); - if (currentValue) - *currentValue = expectedValue; - return tmp; - } - - template - static bool testAndSetRelease(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW - { - bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_release, std::memory_order_relaxed); - if (currentValue) - *currentValue = expectedValue; - return tmp; - } - - template - static bool testAndSetOrdered(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW - { - bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acq_rel, std::memory_order_acquire); - if (currentValue) - *currentValue = expectedValue; - return tmp; - } - - static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return isTestAndSetNative(); } - static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return false; } - - template - static T fetchAndStoreRelaxed(std::atomic &_q_value, T newValue) Q_DECL_NOTHROW - { - return _q_value.exchange(newValue, std::memory_order_relaxed); - } - - template - static T fetchAndStoreAcquire(std::atomic &_q_value, T newValue) Q_DECL_NOTHROW - { - return _q_value.exchange(newValue, std::memory_order_acquire); - } - - template - static T fetchAndStoreRelease(std::atomic &_q_value, T newValue) Q_DECL_NOTHROW - { - return _q_value.exchange(newValue, std::memory_order_release); - } - - template - static T fetchAndStoreOrdered(std::atomic &_q_value, T newValue) Q_DECL_NOTHROW - { - return _q_value.exchange(newValue, std::memory_order_acq_rel); - } - - static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return isTestAndSetNative(); } - static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return false; } - - template static inline - T fetchAndAddRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_add(valueToAdd, std::memory_order_relaxed); - } - - template static inline - T fetchAndAddAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_add(valueToAdd, std::memory_order_acquire); - } - - template static inline - T fetchAndAddRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_add(valueToAdd, std::memory_order_release); - } - - template static inline - T fetchAndAddOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_add(valueToAdd, std::memory_order_acq_rel); - } - - template static inline - T fetchAndSubRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_sub(valueToAdd, std::memory_order_relaxed); - } - - template static inline - T fetchAndSubAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_sub(valueToAdd, std::memory_order_acquire); - } - - template static inline - T fetchAndSubRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_sub(valueToAdd, std::memory_order_release); - } - - template static inline - T fetchAndSubOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_sub(valueToAdd, std::memory_order_acq_rel); - } - - template static inline - T fetchAndAndRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_and(valueToAdd, std::memory_order_relaxed); - } - - template static inline - T fetchAndAndAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_and(valueToAdd, std::memory_order_acquire); - } - - template static inline - T fetchAndAndRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_and(valueToAdd, std::memory_order_release); - } - - template static inline - T fetchAndAndOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_and(valueToAdd, std::memory_order_acq_rel); - } - - template static inline - T fetchAndOrRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_or(valueToAdd, std::memory_order_relaxed); - } - - template static inline - T fetchAndOrAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_or(valueToAdd, std::memory_order_acquire); - } - - template static inline - T fetchAndOrRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_or(valueToAdd, std::memory_order_release); - } - - template static inline - T fetchAndOrOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_or(valueToAdd, std::memory_order_acq_rel); - } - - template static inline - T fetchAndXorRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_xor(valueToAdd, std::memory_order_relaxed); - } - - template static inline - T fetchAndXorAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_xor(valueToAdd, std::memory_order_acquire); - } - - template static inline - T fetchAndXorRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_xor(valueToAdd, std::memory_order_release); - } - - template static inline - T fetchAndXorOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return _q_value.fetch_xor(valueToAdd, std::memory_order_acq_rel); - } -}; - -#if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS) -# define Q_BASIC_ATOMIC_INITIALIZER(a) { a } -#else -# define Q_BASIC_ATOMIC_INITIALIZER(a) { ATOMIC_VAR_INIT(a) } -#endif - -QT_END_NAMESPACE - -#endif // QATOMIC_CXX0X_H diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index 3db2e2ceb8..7f62a6f1b0 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -32,7 +32,6 @@ ANDROID_PERMISSIONS = \ freebsd|openbsd: QMAKE_LFLAGS_NOUNDEF = include(animation/animation.pri) -include(arch/arch.pri) include(global/global.pri) include(thread/thread.pri) include(tools/tools.pri) diff --git a/src/corelib/thread/qatomic_bootstrap.h b/src/corelib/thread/qatomic_bootstrap.h new file mode 100644 index 0000000000..b463f817bd --- /dev/null +++ b/src/corelib/thread/qatomic_bootstrap.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2011 Thiago Macieira +** 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_BOOTSTRAP_H +#define QATOMIC_BOOTSTRAP_H + +#include + +QT_BEGIN_NAMESPACE + +#if 0 +// silence syncqt warnings +QT_END_NAMESPACE +#pragma qt_sync_skip_header_check +#pragma qt_sync_stop_processing +#endif + +template struct QAtomicOps: QGenericAtomicOps > +{ + typedef T Type; + + static bool ref(T &_q_value) Q_DECL_NOTHROW + { + return ++_q_value != 0; + } + static bool deref(T &_q_value) Q_DECL_NOTHROW + { + return --_q_value != 0; + } + + static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW + { + if (currentValue) + *currentValue = _q_value; + if (_q_value == expectedValue) { + _q_value = newValue; + return true; + } + return false; + } + + static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW + { + T tmp = _q_value; + _q_value = newValue; + return tmp; + } + + template static + T fetchAndAddRelaxed(T &_q_value, AdditiveType valueToAdd) Q_DECL_NOTHROW + { + T returnValue = _q_value; + _q_value += valueToAdd; + return returnValue; + } +}; + +QT_END_NAMESPACE + +#endif // QATOMIC_BOOTSTRAP_H diff --git a/src/corelib/thread/qatomic_cxx11.h b/src/corelib/thread/qatomic_cxx11.h new file mode 100644 index 0000000000..2fc0bf5419 --- /dev/null +++ b/src/corelib/thread/qatomic_cxx11.h @@ -0,0 +1,473 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Thiago Macieira +** 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_CXX11_H +#define QATOMIC_CXX11_H + +#include +#include + +QT_BEGIN_NAMESPACE + +#if 0 +// silence syncqt warnings +QT_END_NAMESPACE +#pragma qt_sync_skip_header_check +#pragma qt_sync_stop_processing +#endif + +/* Attempt to detect whether the atomic operations exist in hardware + * or whether they are emulated by way of a lock. + * + * C++11 29.4 [atomics.lockfree] p1 says + * + * The ATOMIC_..._LOCK_FREE macros indicate the lock-free property of the + * corresponding atomic types, with the signed and unsigned variants grouped + * together. The properties also apply to the corresponding (partial) + * specializations of the atomic template. A value of 0 indicates that the + * types are never lock-free. A value of 1 indicates that the types are + * sometimes lock-free. A value of 2 indicates that the types are always + * lock-free. + * + * We have a problem when the value is 1: we'd need to check at runtime, but + * QAtomicInteger requires a constexpr answer (defect introduced in Qt 5.0). So + * we'll err in the side of caution and say it isn't. + */ + +// ### Qt 6: make non-constexpr (see above) +template struct QAtomicTraits +{ static Q_DECL_CONSTEXPR inline bool isLockFree(); }; + +#define Q_ATOMIC_INT32_IS_SUPPORTED +#if ATOMIC_INT_LOCK_FREE == 2 +# define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree() +{ return true; } +#elif ATOMIC_INT_LOCK_FREE == 1 +# define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT32_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_SOMETIMES_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree() +{ return false; } +#else +# define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NEVER_NATIVE +# define Q_ATOMIC_INT_TEST_AND_SET_IS_NEVER_NATIVE +# define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NEVER_NATIVE +# define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NEVER_NATIVE +# define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_NEVER_NATIVE +# define Q_ATOMIC_INT32_TEST_AND_SET_IS_NEVER_NATIVE +# define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_NEVER_NATIVE +# define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_NEVER_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree() +{ return false; } +#endif + +#if ATOMIC_POINTER_LOCK_FREE == 2 +# define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#elif ATOMIC_POINTER_LOCK_FREE == 1 +# define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE +#else +# define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_NEVER_NATIVE +# define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NEVER_NATIVE +# define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NEVER_NATIVE +# define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NEVER_NATIVE +#endif + +template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; }; +#define Q_ATOMIC_INT8_IS_SUPPORTED +#if ATOMIC_CHAR_LOCK_FREE == 2 +# define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT8_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree() +{ return true; } +#elif ATOMIC_CHAR_LOCK_FREE == 1 +# define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT8_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_SOMETIMES_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree() +{ return false; } +#else +# define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_NEVER_NATIVE +# define Q_ATOMIC_INT8_TEST_AND_SET_IS_NEVER_NATIVE +# define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_NEVER_NATIVE +# define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_NEVER_NATIVE + +template <> Q_DECL_CONSTEXPR bool QAtomicTraits<1>::isLockFree() +{ return false; } +#endif + +template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; }; +#define Q_ATOMIC_INT16_IS_SUPPORTED +#if ATOMIC_SHORT_LOCK_FREE == 2 +# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree() +{ return false; } +#elif ATOMIC_SHORT_LOCK_FREE == 1 +# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT16_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree() +{ return false; } +#else +# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE +# define Q_ATOMIC_INT16_TEST_AND_SET_IS_NEVER_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree() +{ return false; } +#endif + +#if QT_CONFIG(std_atomic64) +template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; +# define Q_ATOMIC_INT64_IS_SUPPORTED +# if ATOMIC_LLONG_LOCK_FREE == 2 +# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() +{ return true; } +# elif ATOMIC_LLONG_LOCK_FREE == 1 +# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT16_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() +{ return false; } +# else +# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE +# define Q_ATOMIC_INT16_TEST_AND_SET_IS_NEVER_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() +{ return false; } +# endif +#endif + +template struct QAtomicOps +{ + typedef std::atomic Type; + + template static inline + T load(const std::atomic &_q_value) Q_DECL_NOTHROW + { + return _q_value.load(std::memory_order_relaxed); + } + + template static inline + T load(const volatile std::atomic &_q_value) Q_DECL_NOTHROW + { + return _q_value.load(std::memory_order_relaxed); + } + + template static inline + T loadAcquire(const std::atomic &_q_value) Q_DECL_NOTHROW + { + return _q_value.load(std::memory_order_acquire); + } + + template static inline + T loadAcquire(const volatile std::atomic &_q_value) Q_DECL_NOTHROW + { + return _q_value.load(std::memory_order_acquire); + } + + template static inline + void store(std::atomic &_q_value, T newValue) Q_DECL_NOTHROW + { + _q_value.store(newValue, std::memory_order_relaxed); + } + + template static inline + void storeRelease(std::atomic &_q_value, T newValue) Q_DECL_NOTHROW + { + _q_value.store(newValue, std::memory_order_release); + } + + static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return isTestAndSetNative(); } + static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return false; } + template + static inline bool ref(std::atomic &_q_value) + { + return ++_q_value != 0; + } + + template + static inline bool deref(std::atomic &_q_value) Q_DECL_NOTHROW + { + return --_q_value != 0; + } + + static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW + { return QAtomicTraits::isLockFree(); } + static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; } + + template + static bool testAndSetRelaxed(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW + { + bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed); + if (currentValue) + *currentValue = expectedValue; + return tmp; + } + + template + static bool testAndSetAcquire(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW + { + bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acquire, std::memory_order_acquire); + if (currentValue) + *currentValue = expectedValue; + return tmp; + } + + template + static bool testAndSetRelease(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW + { + bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_release, std::memory_order_relaxed); + if (currentValue) + *currentValue = expectedValue; + return tmp; + } + + template + static bool testAndSetOrdered(std::atomic &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) Q_DECL_NOTHROW + { + bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acq_rel, std::memory_order_acquire); + if (currentValue) + *currentValue = expectedValue; + return tmp; + } + + static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return isTestAndSetNative(); } + static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return false; } + + template + static T fetchAndStoreRelaxed(std::atomic &_q_value, T newValue) Q_DECL_NOTHROW + { + return _q_value.exchange(newValue, std::memory_order_relaxed); + } + + template + static T fetchAndStoreAcquire(std::atomic &_q_value, T newValue) Q_DECL_NOTHROW + { + return _q_value.exchange(newValue, std::memory_order_acquire); + } + + template + static T fetchAndStoreRelease(std::atomic &_q_value, T newValue) Q_DECL_NOTHROW + { + return _q_value.exchange(newValue, std::memory_order_release); + } + + template + static T fetchAndStoreOrdered(std::atomic &_q_value, T newValue) Q_DECL_NOTHROW + { + return _q_value.exchange(newValue, std::memory_order_acq_rel); + } + + static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return isTestAndSetNative(); } + static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return false; } + + template static inline + T fetchAndAddRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_add(valueToAdd, std::memory_order_relaxed); + } + + template static inline + T fetchAndAddAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_add(valueToAdd, std::memory_order_acquire); + } + + template static inline + T fetchAndAddRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_add(valueToAdd, std::memory_order_release); + } + + template static inline + T fetchAndAddOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_add(valueToAdd, std::memory_order_acq_rel); + } + + template static inline + T fetchAndSubRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_sub(valueToAdd, std::memory_order_relaxed); + } + + template static inline + T fetchAndSubAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_sub(valueToAdd, std::memory_order_acquire); + } + + template static inline + T fetchAndSubRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_sub(valueToAdd, std::memory_order_release); + } + + template static inline + T fetchAndSubOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_sub(valueToAdd, std::memory_order_acq_rel); + } + + template static inline + T fetchAndAndRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_and(valueToAdd, std::memory_order_relaxed); + } + + template static inline + T fetchAndAndAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_and(valueToAdd, std::memory_order_acquire); + } + + template static inline + T fetchAndAndRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_and(valueToAdd, std::memory_order_release); + } + + template static inline + T fetchAndAndOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_and(valueToAdd, std::memory_order_acq_rel); + } + + template static inline + T fetchAndOrRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_or(valueToAdd, std::memory_order_relaxed); + } + + template static inline + T fetchAndOrAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_or(valueToAdd, std::memory_order_acquire); + } + + template static inline + T fetchAndOrRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_or(valueToAdd, std::memory_order_release); + } + + template static inline + T fetchAndOrOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_or(valueToAdd, std::memory_order_acq_rel); + } + + template static inline + T fetchAndXorRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_xor(valueToAdd, std::memory_order_relaxed); + } + + template static inline + T fetchAndXorAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_xor(valueToAdd, std::memory_order_acquire); + } + + template static inline + T fetchAndXorRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_xor(valueToAdd, std::memory_order_release); + } + + template static inline + T fetchAndXorOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_xor(valueToAdd, std::memory_order_acq_rel); + } +}; + +#if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS) +# define Q_BASIC_ATOMIC_INITIALIZER(a) { a } +#else +# define Q_BASIC_ATOMIC_INITIALIZER(a) { ATOMIC_VAR_INIT(a) } +#endif + +QT_END_NAMESPACE + +#endif // QATOMIC_CXX0X_H diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index e4972a57b3..47775f3fde 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -10,6 +10,8 @@ HEADERS += thread/qmutex.h \ thread/qthreadstorage.h \ thread/qwaitcondition.h \ thread/qatomic.h \ + thread/qatomic_bootstrap.h \ + thread/qatomic_cxx11.h \ thread/qbasicatomic.h \ thread/qgenericatomic.h @@ -67,3 +69,5 @@ win32 { thread/qthread_unix.cpp \ thread/qwaitcondition_unix.cpp } + +qtConfig(std-atomic64): QMAKE_USE += libatomic -- cgit v1.2.3 From 081c001deb75fa38385d3ff8cbbdb4f788529133 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 5 Mar 2018 19:53:37 -0800 Subject: QSemaphore: fix deadlock when the woken up thread wakes up another When the thread that got woken up by release() is supposed to release() to wake up another thread, we were deadlocking. This happened because we cleared the bit indicating that there was contention when the first release(). Instead of storing a single bit, we now store the number of threads waiting. Task-number: QTBUG-66875 Change-Id: I72f5230ad59948f784eafffd15193873502ecba4 Reviewed-by: Lars Knoll --- src/corelib/thread/qsemaphore.cpp | 131 +++++++++++++++++++++++++------------- 1 file changed, 88 insertions(+), 43 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index 012628ef63..f4674fcc1d 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2017 Intel Corporation. +** Copyright (C) 2018 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -119,28 +119,37 @@ using namespace QtFutex; acquire tokens. Which ones get woken up is unspecified. If the system has the ability to wake up a precise number of threads, has - Linux's FUTEX_WAKE_OP functionality, and is 64-bit, we'll use the high word - as a copy of the low word, but the sign bit indicating the presence of a - thread waiting for multiple tokens. So when releasing n tokens on those - systems, we tell the kernel to wake up n single-token threads and all of - the multi-token ones, then clear that wait bit. Which threads get woken up - is unspecified, but it's likely single-token threads will get woken up - first. + Linux's FUTEX_WAKE_OP functionality, and is 64-bit, instead of using a + single bit indicating a contended semaphore, we'll store the total number + of waiters in the high word. Additionally, all multi-token waiters will be + waiting on that high word. So when releasing n tokens on those systems, we + tell the kernel to wake up n single-token threads and all of the + multi-token ones. Which threads get woken up is unspecified, but it's + likely single-token threads will get woken up first. */ -static const quint32 futexContendedBit = 1U << 31; + +#if defined(FUTEX_OP) && QT_POINTER_SIZE > 4 +static Q_CONSTEXPR bool futexHasWaiterCount = true; +#else +static Q_CONSTEXPR bool futexHasWaiterCount = false; +#endif + +static const quintptr futexNeedsWakeAllBit = + Q_UINT64_C(1) << (sizeof(quintptr) * CHAR_BIT - 1); static int futexAvailCounter(quintptr v) { // the low 31 bits - return int(v & (futexContendedBit - 1)); + return int(v & 0x7fffffffU); } -static quintptr futexCounterParcel(int n) +static bool futexNeedsWake(quintptr v) { - // replicate the 31 bits if we're on 64-bit - quint64 nn = quint32(n); - nn |= (nn << 32); - return quintptr(nn); + // If we're counting waiters, the number of waiters is stored in the low 31 + // bits of the high word (that is, bits 32-62). If we're not, then we use + // bit 31 to indicate anyone is waiting. Either way, if any bit 31 or above + // is set, there are waiters. + return v >> 31; } static QBasicAtomicInteger *futexLow32(QBasicAtomicInteger *ptr) @@ -152,9 +161,6 @@ static QBasicAtomicInteger *futexLow32(QBasicAtomicInteger *p return result; } -#ifdef FUTEX_OP -// quintptr might be 32bit, in which case we want this to be 0, without implicitly casting. -static const quintptr futexMultiWaiterBit = static_cast(Q_UINT64_C(1) << 63); static QBasicAtomicInteger *futexHigh32(QBasicAtomicInteger *ptr) { auto result = reinterpret_cast *>(ptr); @@ -163,18 +169,21 @@ static QBasicAtomicInteger *futexHigh32(QBasicAtomicInteger * #endif return result; } -#endif -template bool futexSemaphoreTryAcquire(QBasicAtomicInteger &u, int n, int timeout) +template bool +futexSemaphoreTryAcquire_loop(QBasicAtomicInteger &u, quintptr curValue, quintptr nn, int timeout) { QDeadlineTimer timer(IsTimed ? QDeadlineTimer(timeout) : QDeadlineTimer()); - quintptr curValue = u.loadAcquire(); qint64 remainingTime = timeout * Q_INT64_C(1000) * 1000; + int n = int(unsigned(nn)); + + // we're called after one testAndSet, so start by waiting first + goto start_wait; + forever { - int available = futexAvailCounter(curValue); - if (available >= n) { + if (futexAvailCounter(curValue) >= n) { // try to acquire - quintptr newValue = curValue - futexCounterParcel(n); + quintptr newValue = curValue - nn; if (u.testAndSetOrdered(curValue, newValue, curValue)) return true; // succeeded! continue; @@ -184,19 +193,18 @@ template bool futexSemaphoreTryAcquire(QBasicAtomicInteger 1 && sizeof(curValue) >= sizeof(int)) { - bitsToSet |= futexMultiWaiterBit; - ptr = futexHigh32(&u); + if (n > 1 || !futexHasWaiterCount) { + u.fetchAndOrRelaxed(futexNeedsWakeAllBit); + curValue |= futexNeedsWakeAllBit; + if (n > 1 && futexHasWaiterCount) { + ptr = futexHigh32(&u); + //curValue >>= 32; // but this is UB in 32-bit, so roundabout: + curValue = quint64(curValue) >> 32; + } } -#endif - - // the value is the same for either branch - u.fetchAndOrRelaxed(bitsToSet); - curValue |= bitsToSet; if (IsTimed && remainingTime > 0) { bool timedout = !futexWait(*ptr, curValue, remainingTime); @@ -212,6 +220,47 @@ template bool futexSemaphoreTryAcquire(QBasicAtomicInteger bool futexSemaphoreTryAcquire(QBasicAtomicInteger &u, int n, int timeout) +{ + // Try to acquire without waiting (we still loop because the testAndSet + // call can fail). + quintptr curValue = u.loadAcquire(); + while (futexAvailCounter(curValue) >= n) { + // try to acquire + quintptr newValue = curValue - n; + if (u.testAndSetOrdered(curValue, newValue, curValue)) + return true; // succeeded! + } + if (timeout == 0) + return false; + + // we need to wait + quintptr valueToSubtract = unsigned(n); + quintptr oneWaiter = quintptr(Q_UINT64_C(1) << 32); // zero on 32-bit + if (futexHasWaiterCount) { + // increase the waiter count + u.fetchAndAddRelaxed(oneWaiter); + + // We don't use the fetched value from above so futexWait() fails if + // it changed after the testAndSetOrdered above. + curValue += oneWaiter; + + // Also adjust valueToSubtract to subtract oneWaiter when we succeed in + // acquiring. + valueToSubtract += oneWaiter; + } + + if (futexSemaphoreTryAcquire_loop(u, curValue, valueToSubtract, timeout)) + return true; + + if (futexHasWaiterCount) { + // decrement the number of threads waiting + Q_ASSERT(futexHigh32(&u)->load() & 0x7fffffffU); + u.fetchAndSubRelaxed(oneWaiter); + } + return false; +} + class QSemaphorePrivate { public: inline QSemaphorePrivate(int n) : avail(n) { } @@ -289,10 +338,10 @@ void QSemaphore::release(int n) Q_ASSERT_X(n >= 0, "QSemaphore::release", "parameter 'n' must be non-negative"); if (futexAvailable()) { - quintptr prevValue = u.fetchAndAddRelease(futexCounterParcel(n)); - if (prevValue & futexContendedBit) { + quintptr prevValue = u.fetchAndAddRelease(n); + if (futexNeedsWake(prevValue)) { #ifdef FUTEX_OP - if (sizeof(u) == sizeof(int)) { + if (!futexHasWaiterCount) { /* On 32-bit systems, all waiters are waiting on the same address, so we'll wake them all and ask the kernel to clear the high bit. @@ -317,9 +366,6 @@ void QSemaphore::release(int n) the kernel to wake up n single-token waiters and all multi-token waiters (if any), then clear the multi-token wait bit. - That means we must clear the contention bit ourselves. See - below for handling the race. - atomic { int oldval = *upper; *upper = oldval & ~(1 << 31); @@ -332,7 +378,6 @@ void QSemaphore::release(int n) quint32 oparg = 31; quint32 cmp = FUTEX_OP_CMP_LT; quint32 cmparg = 0; - futexLow32(&u)->fetchAndAndRelease(futexContendedBit - 1); futexWakeOp(*futexLow32(&u), n, INT_MAX, *futexHigh32(&u), FUTEX_OP(op, oparg, cmp, cmparg)); } #else @@ -343,7 +388,7 @@ void QSemaphore::release(int n) // its acquisition anyway, so it has to wait; // 2) it did not see the new counter value, in which case its // futexWait will fail. - u.fetchAndAndRelease(futexContendedBit - 1); + u.fetchAndAndRelease(futexNeedsWakeAllBit - 1); futexWakeAll(u); #endif } -- cgit v1.2.3 From dabc76de80e3b433a1a8e2354ca78a34389ea9f8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 10 Mar 2018 11:26:04 -0800 Subject: QSemaphore: add minor optimization for 64-bit Linux systems Since we won't use the high bit of the low 32-bit word at all, we don't need the AND with 0x7fffffff either. Just cast. Change-Id: I72f5230ad59948f784eafffd151aa5a7dee995db Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/thread/qsemaphore.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/corelib') diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index f4674fcc1d..c2e4d7d9d1 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -140,6 +140,13 @@ static const quintptr futexNeedsWakeAllBit = static int futexAvailCounter(quintptr v) { // the low 31 bits + if (futexHasWaiterCount) { + // the high bit of the low word isn't used + Q_ASSERT((v & 0x80000000U) == 0); + + // so we can be a little faster + return int(unsigned(v)); + } return int(v & 0x7fffffffU); } -- cgit v1.2.3 From 323b00e38c38cc864d136d70befd106400c50163 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 10 Feb 2018 10:08:16 -0800 Subject: QSharedDataPointer: use swap-and-move in the move constructor This makes the pointer that was in the moved-into object be destroyed before the return of this function (if the reference count was 1), instead of letting it live in the moved-from object. Task-number: QTBUG-66322 Change-Id: I3debfc11127e4516b505fffd151209292bd3adaa Reviewed-by: Lars Knoll --- src/corelib/tools/qshareddata.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index dbf0907a0f..780f2331a8 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -115,7 +115,11 @@ public: #ifdef Q_COMPILER_RVALUE_REFS QSharedDataPointer(QSharedDataPointer &&o) Q_DECL_NOTHROW : d(o.d) { o.d = nullptr; } inline QSharedDataPointer &operator=(QSharedDataPointer &&other) Q_DECL_NOTHROW - { qSwap(d, other.d); return *this; } + { + QSharedDataPointer moved(std::move(other)); + swap(moved); + return *this; + } #endif inline bool operator!() const { return !d; } @@ -204,7 +208,11 @@ public: #ifdef Q_COMPILER_RVALUE_REFS inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) Q_DECL_NOTHROW : d(o.d) { o.d = nullptr; } inline QExplicitlySharedDataPointer &operator=(QExplicitlySharedDataPointer &&other) Q_DECL_NOTHROW - { qSwap(d, other.d); return *this; } + { + QExplicitlySharedDataPointer moved(std::move(other)); + swap(moved); + return *this; + } #endif inline bool operator!() const { return !d; } -- cgit v1.2.3 From 5a4787dca01c302dd462a76222dfbf28c8951a8d Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 9 Feb 2018 14:29:21 +0100 Subject: Modernize the "regularexpression" feature Use QT_CONFIG(regularexpression), disentangle it from QT_BOOTSTRAPPED, switch it off in the bootstrap build, remove the #ifdefs from qregularexpression.{h|cpp}, and add QT_REQUIRE_CONFIG(regularexpression) to the header. qregularexpression.{h|cpp} are already correctly excluded in tools.pri if !qtConfig(regularexpression). Change-Id: I21de154a6a118b76f99003d3acb72ac1e220d302 Reviewed-by: Oswald Buddenhagen --- src/corelib/global/qlogging.cpp | 4 ++-- src/corelib/io/qstandardpaths_unix.cpp | 2 ++ src/corelib/kernel/qmetatype.cpp | 17 ++++++++++------- src/corelib/kernel/qmetatype_p.h | 2 +- src/corelib/kernel/qobject.cpp | 8 +++++--- src/corelib/kernel/qobject.h | 6 +++--- src/corelib/kernel/qvariant.cpp | 16 +++++++++------- src/corelib/kernel/qvariant.h | 16 ++++++++-------- src/corelib/tools/qregularexpression.cpp | 4 ---- src/corelib/tools/qregularexpression.h | 6 ++---- src/corelib/tools/qstring.cpp | 30 ++++++++++++------------------ src/corelib/tools/qstring.h | 8 ++++---- src/corelib/tools/qstringlist.cpp | 22 +++++++++------------- src/corelib/tools/qstringlist.h | 24 ++++++++---------------- 14 files changed, 75 insertions(+), 90 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 99c57c3b7a..17002c4231 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -91,8 +91,7 @@ # include "private/qcore_unix_p.h" #endif -#ifndef QT_BOOTSTRAPPED -#if !defined QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) # ifdef __UCLIBC__ # if __UCLIBC_HAS_BACKTRACE__ # define QLOGGING_HAVE_BACKTRACE @@ -106,6 +105,7 @@ extern char *__progname; #endif +#ifndef QT_BOOTSTRAPPED #if defined(Q_OS_LINUX) && (defined(__GLIBC__) || QT_HAS_INCLUDE()) # include diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp index e49edd9a40..748ce67dac 100644 --- a/src/corelib/io/qstandardpaths_unix.cpp +++ b/src/corelib/io/qstandardpaths_unix.cpp @@ -42,7 +42,9 @@ #include #include #include +#if QT_CONFIG(regularexpression) #include +#endif #include #include #include diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 5abc2ebd70..518381712a 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -53,12 +53,15 @@ #include "qdatastream.h" #include "qmetatypeswitcher_p.h" +#if QT_CONFIG(regularexpression) +# include "qregularexpression.h" +#endif + #ifndef QT_BOOTSTRAPPED # include "qbitarray.h" # include "qurl.h" # include "qvariant.h" # include "qabstractitemmodel.h" -# include "qregularexpression.h" # include "qjsonvalue.h" # include "qjsonobject.h" # include "qjsonarray.h" @@ -1481,12 +1484,12 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data) stream << *static_cast(data); break; #endif -#ifndef QT_BOOTSTRAPPED -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) case QMetaType::QRegularExpression: stream << *static_cast(data); break; -#endif // QT_NO_REGULAREXPRESSION +#endif // QT_CONFIG(regularexpression) +#ifndef QT_BOOTSTRAPPED case QMetaType::QEasingCurve: stream << *static_cast(data); break; @@ -1711,12 +1714,12 @@ bool QMetaType::load(QDataStream &stream, int type, void *data) stream >> *static_cast< NS(QRegExp)*>(data); break; #endif -#ifndef QT_BOOTSTRAPPED -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) case QMetaType::QRegularExpression: stream >> *static_cast< NS(QRegularExpression)*>(data); break; -#endif // QT_NO_REGULAREXPRESSION +#endif // QT_CONFIG(regularexpression) +#ifndef QT_BOOTSTRAPPED case QMetaType::QEasingCurve: stream >> *static_cast< NS(QEasingCurve)*>(data); break; diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h index 6f1334d082..0bf6bcb922 100644 --- a/src/corelib/kernel/qmetatype_p.h +++ b/src/corelib/kernel/qmetatype_p.h @@ -219,7 +219,7 @@ template<> struct TypeDefinition { static const bool IsAvailable = fals #ifdef QT_NO_REGEXP template<> struct TypeDefinition { static const bool IsAvailable = false; }; #endif -#if defined(QT_BOOTSTRAPPED) || defined(QT_NO_REGULAREXPRESSION) +#if !QT_CONFIG(regularexpression) template<> struct TypeDefinition { static const bool IsAvailable = false; }; #endif #ifdef QT_NO_SHORTCUT diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 9e1c3a50cb..dcc1bb5814 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -50,7 +50,9 @@ #include "qvariant.h" #include "qmetaobject.h" #include -#include +#if QT_CONFIG(regularexpression) +# include +#endif #include #include #include @@ -1921,7 +1923,7 @@ void qt_qFindChildren_helper(const QObject *parent, const QRegExp &re, } #endif // QT_NO_REGEXP -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) /*! \internal */ @@ -1943,7 +1945,7 @@ void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re qt_qFindChildren_helper(obj, re, mo, list, options); } } -#endif // QT_NO_REGULAREXPRESSION +#endif // QT_CONFIG(regularexpression) /*! \internal diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 0e608a3208..aac9bcdee9 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -74,7 +74,7 @@ class QWidget; #ifndef QT_NO_REGEXP class QRegExp; #endif -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) class QRegularExpression; #endif #ifndef QT_NO_USERDATA @@ -187,7 +187,7 @@ public: } #endif -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) template inline QList findChildren(const QRegularExpression &re, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const { @@ -197,7 +197,7 @@ public: reinterpret_cast *>(&list), options); return list; } -#endif +#endif // QT_CONFIG(regularexpression) inline const QObjectList &children() const { return d_ptr->children; } diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index f77831c703..c3c36e05d7 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -48,7 +48,9 @@ #include "qdatetime.h" #include "qeasingcurve.h" #include "qlist.h" +#if QT_CONFIG(regularexpression) #include "qregularexpression.h" +#endif #include "qstring.h" #include "qstringlist.h" #include "qurl.h" @@ -1941,12 +1943,12 @@ QVariant::QVariant(const QRegExp ®Exp) : d(RegExp) { v_construct(&d, regExp); } #endif // QT_NO_REGEXP -#ifndef QT_BOOTSTRAPPED -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) QVariant::QVariant(const QRegularExpression &re) : d(RegularExpression) { v_construct(&d, re); } -#endif +#endif // QT_CONFIG(regularexpression) +#ifndef QT_BOOTSTRAPPED QVariant::QVariant(const QUuid &uuid) : d(Uuid) { v_construct(&d, uuid); } @@ -2650,7 +2652,7 @@ QRegExp QVariant::toRegExp() const } #endif -#ifndef QT_BOOTSTRAPPED +#if QT_CONFIG(regularexpression) /*! \fn QRegularExpression QVariant::toRegularExpression() const \since 5.0 @@ -2660,13 +2662,13 @@ QRegExp QVariant::toRegExp() const \sa canConvert(), convert() */ -#ifndef QT_NO_REGULAREXPRESSION QRegularExpression QVariant::toRegularExpression() const { return qVariantToHelper(d, handlerManager); } -#endif // QT_NO_REGULAREXPRESSION +#endif // QT_CONFIG(regularexpression) +#ifndef QT_BOOTSTRAPPED /*! \since 5.0 @@ -2758,7 +2760,7 @@ QJsonDocument QVariant::toJsonDocument() const { return qVariantToHelper(d, handlerManager); } -#endif +#endif // QT_BOOTSTRAPPED /*! \fn QChar QVariant::toChar() const diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 7ce4e1a4d8..361768ef00 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -81,9 +81,9 @@ class QRectF; #ifndef QT_NO_REGEXP class QRegExp; #endif // QT_NO_REGEXP -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) class QRegularExpression; -#endif // QT_NO_REGULAREXPRESSION +#endif // QT_CONFIG(regularexpression) class QTextFormat; class QTextLength; class QUrl; @@ -248,10 +248,10 @@ class Q_CORE_EXPORT QVariant #ifndef QT_NO_REGEXP QVariant(const QRegExp ®Exp); #endif // QT_NO_REGEXP -#ifndef QT_BOOTSTRAPPED -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) QVariant(const QRegularExpression &re); -#endif // QT_NO_REGULAREXPRESSION +#endif // QT_CONFIG(regularexpression) +#ifndef QT_BOOTSTRAPPED QVariant(const QUrl &url); QVariant(const QEasingCurve &easing); QVariant(const QUuid &uuid); @@ -322,10 +322,10 @@ class Q_CORE_EXPORT QVariant #ifndef QT_NO_REGEXP QRegExp toRegExp() const; #endif // QT_NO_REGEXP -#ifndef QT_BOOTSTRAPPED -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) QRegularExpression toRegularExpression() const; -#endif // QT_NO_REGULAREXPRESSION +#endif // QT_CONFIG(regularexpression) +#ifndef QT_BOOTSTRAPPED QUrl toUrl() const; QEasingCurve toEasingCurve() const; QUuid toUuid() const; diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 86bc99716d..13eff07c04 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -41,8 +41,6 @@ #include "qregularexpression.h" -#ifndef QT_NO_REGULAREXPRESSION - #include #include #include @@ -2912,5 +2910,3 @@ static const char *pcreCompileErrorCodes[] = #endif // #if 0 QT_END_NAMESPACE - -#endif // QT_NO_REGULAREXPRESSION diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h index 050841e70e..398fc9ec9c 100644 --- a/src/corelib/tools/qregularexpression.h +++ b/src/corelib/tools/qregularexpression.h @@ -43,13 +43,13 @@ #include -#ifndef QT_NO_REGULAREXPRESSION - #include #include #include #include +QT_REQUIRE_CONFIG(regularexpression); + QT_BEGIN_NAMESPACE class QStringView; @@ -277,6 +277,4 @@ Q_DECLARE_SHARED(QRegularExpressionMatchIterator) QT_END_NAMESPACE -#endif // QT_NO_REGULAREXPRESSION - #endif // QREGULAREXPRESSION_H diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index b56ad34546..f6360f5504 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -40,7 +40,9 @@ #include "qstringlist.h" #include "qregexp.h" +#if QT_CONFIG(regularexpression) #include "qregularexpression.h" +#endif #include "qunicodetables_p.h" #ifndef QT_NO_TEXTCODEC #include @@ -3695,7 +3697,7 @@ int QString::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs } -#if !(defined(QT_NO_REGEXP) && defined(QT_NO_REGULAREXPRESSION)) +#if !(defined(QT_NO_REGEXP) && !QT_CONFIG(regularexpression)) struct QStringCapture { int pos; @@ -3862,8 +3864,7 @@ QString& QString::replace(const QRegExp &rx, const QString &after) } #endif -#ifndef QT_NO_REGULAREXPRESSION -#ifndef QT_BOOTSTRAPPED +#if QT_CONFIG(regularexpression) /*! \overload replace() \since 5.0 @@ -3991,8 +3992,7 @@ QString &QString::replace(const QRegularExpression &re, const QString &after) return *this; } -#endif // QT_BOOTSTRAPPED -#endif // QT_NO_REGULAREXPRESSION +#endif // QT_CONFIG(regularexpression) /*! Returns the number of (potentially overlapping) occurrences of @@ -4207,8 +4207,7 @@ int QString::count(const QRegExp& rx) const } #endif // QT_NO_REGEXP -#ifndef QT_NO_REGULAREXPRESSION -#ifndef QT_BOOTSTRAPPED +#if QT_CONFIG(regularexpression) /*! \overload indexOf() \since 5.0 @@ -4386,8 +4385,7 @@ int QString::count(const QRegularExpression &re) const } return count; } -#endif // QT_BOOTSTRAPPED -#endif // QT_NO_REGULAREXPRESSION +#endif // QT_CONFIG(regularexpression) /*! \fn int QString::count() const @@ -4509,7 +4507,7 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl return ret; } -#if !(defined(QT_NO_REGEXP) && defined(QT_NO_REGULAREXPRESSION)) +#if !(defined(QT_NO_REGEXP) && !QT_CONFIG(regularexpression)) class qt_section_chunk { public: qt_section_chunk() {} @@ -4619,8 +4617,7 @@ QString QString::section(const QRegExp ®, int start, int end, SectionFlags fl } #endif -#ifndef QT_NO_REGULAREXPRESSION -#ifndef QT_BOOTSTRAPPED +#if QT_CONFIG(regularexpression) /*! \overload section() \since 5.0 @@ -4664,8 +4661,7 @@ QString QString::section(const QRegularExpression &re, int start, int end, Secti return extractSections(sections, start, end, flags); } -#endif // QT_BOOTSTRAPPED -#endif // QT_NO_REGULAREXPRESSION +#endif // QT_CONFIG(regularexpression) /*! Returns a substring that contains the \a n leftmost characters @@ -7586,8 +7582,7 @@ QVector QString::splitRef(const QRegExp &rx, SplitBehavior behavior) } #endif -#ifndef QT_NO_REGULAREXPRESSION -#ifndef QT_BOOTSTRAPPED +#if QT_CONFIG(regularexpression) namespace { template static ResultList splitString(const QString &source, MidMethod mid, const QRegularExpression &re, @@ -7667,8 +7662,7 @@ QVector QString::splitRef(const QRegularExpression &re, SplitBehavio { return splitString >(*this, &QString::midRef, re, behavior); } -#endif // QT_BOOTSTRAPPED -#endif // QT_NO_REGULAREXPRESSION +#endif // QT_CONFIG(regularexpression) /*! \enum QString::NormalizationForm diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index b8f4d49831..f27f7efa2b 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -353,7 +353,7 @@ public: inline bool contains(QRegExp &rx) const { return indexOf(rx) != -1; } #endif -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) int indexOf(const QRegularExpression &re, int from = 0) const; int indexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const; // ### Qt 6: merge overloads int lastIndexOf(const QRegularExpression &re, int from = -1) const; @@ -377,7 +377,7 @@ public: #ifndef QT_NO_REGEXP QString section(const QRegExp ®, int start, int end = -1, SectionFlags flags = SectionDefault) const; #endif -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) QString section(const QRegularExpression &re, int start, int end = -1, SectionFlags flags = SectionDefault) const; #endif Q_REQUIRED_RESULT QString left(int n) const; @@ -502,7 +502,7 @@ public: inline QString &remove(const QRegExp &rx) { return replace(rx, QString()); } #endif -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) QString &replace(const QRegularExpression &re, const QString &after); inline QString &remove(const QRegularExpression &re) { return replace(re, QString()); } @@ -522,7 +522,7 @@ public: Q_REQUIRED_RESULT QStringList split(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const; Q_REQUIRED_RESULT QVector splitRef(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const; #endif -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) Q_REQUIRED_RESULT QStringList split(const QRegularExpression &sep, SplitBehavior behavior = KeepEmptyParts) const; Q_REQUIRED_RESULT QVector splitRef(const QRegularExpression &sep, SplitBehavior behavior = KeepEmptyParts) const; #endif diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp index 17f6bd8539..d10d9ad9d0 100644 --- a/src/corelib/tools/qstringlist.cpp +++ b/src/corelib/tools/qstringlist.cpp @@ -39,7 +39,9 @@ #include #include -#include +#if QT_CONFIG(regularexpression) +# include +#endif #include @@ -361,8 +363,7 @@ QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegExp } #endif -#ifndef QT_BOOTSTRAPPED -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) /*! \fn QStringList QStringList::filter(const QRegularExpression &re) const \overload @@ -380,8 +381,7 @@ QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegula } return res; } -#endif // QT_NO_REGULAREXPRESSION -#endif // QT_BOOTSTRAPPED +#endif // QT_CONFIG(regularexpression) /*! \fn QStringList &QStringList::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs) @@ -436,8 +436,7 @@ void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegExp &r } #endif -#ifndef QT_BOOTSTRAPPED -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) /*! \fn QStringList &QStringList::replaceInStrings(const QRegularExpression &re, const QString &after) \overload @@ -466,8 +465,7 @@ void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegularEx for (int i = 0; i < that->size(); ++i) (*that)[i].replace(re, after); } -#endif // QT_NO_REGULAREXPRESSION -#endif // QT_BOOTSTRAPPED +#endif // QT_CONFIG(regularexpression) static int accumulatedSize(const QStringList &list, int seplen) { @@ -674,8 +672,7 @@ int QtPrivate::QStringList_lastIndexOf(const QStringList *that, QRegExp &rx, int } #endif -#ifndef QT_BOOTSTRAPPED -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) /*! \fn int QStringList::indexOf(const QRegularExpression &re, int from) const \overload @@ -732,8 +729,7 @@ int QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegularEx } return -1; } -#endif // QT_NO_REGULAREXPRESSION -#endif // QT_BOOTSTRAPPED +#endif // QT_CONFIG(regularexpression) /*! \fn int QStringList::removeDuplicates() diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index b11856d9be..e58445b8c0 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -84,12 +84,10 @@ public: inline QStringList &replaceInStrings(const QRegExp &rx, const QString &after); #endif -#ifndef QT_BOOTSTRAPPED -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) inline QStringList filter(const QRegularExpression &re) const; inline QStringList &replaceInStrings(const QRegularExpression &re, const QString &after); -#endif // QT_NO_REGULAREXPRESSION -#endif // QT_BOOTSTRAPPED +#endif // QT_CONFIG(regularexpression) #ifndef Q_QDOC private: @@ -138,12 +136,10 @@ public: inline int lastIndexOf(QRegExp &rx, int from = -1) const; #endif -#ifndef QT_BOOTSTRAPPED -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) inline int indexOf(const QRegularExpression &re, int from = 0) const; inline int lastIndexOf(const QRegularExpression &re, int from = -1) const; -#endif // QT_NO_REGULAREXPRESSION -#endif // QT_BOOTSTRAPPED +#endif // QT_CONFIG(regularexpression) using QList::indexOf; using QList::lastIndexOf; @@ -179,14 +175,12 @@ namespace QtPrivate { int Q_CORE_EXPORT QStringList_lastIndexOf(const QStringList *that, QRegExp &rx, int from); #endif -#ifndef QT_BOOTSTRAPPED -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) void Q_CORE_EXPORT QStringList_replaceInStrings(QStringList *that, const QRegularExpression &rx, const QString &after); QStringList Q_CORE_EXPORT QStringList_filter(const QStringList *that, const QRegularExpression &re); int Q_CORE_EXPORT QStringList_indexOf(const QStringList *that, const QRegularExpression &re, int from); int Q_CORE_EXPORT QStringList_lastIndexOf(const QStringList *that, const QRegularExpression &re, int from); -#endif // QT_NO_REGULAREXPRESSION -#endif // QT_BOOTSTRAPPED +#endif // QT_CONFIG(regularexpression) } inline void QListSpecialMethods::sort(Qt::CaseSensitivity cs) @@ -275,8 +269,7 @@ inline int QStringList::lastIndexOf(QRegExp &rx, int from) const } #endif -#ifndef QT_BOOTSTRAPPED -#ifndef QT_NO_REGULAREXPRESSION +#if QT_CONFIG(regularexpression) inline QStringList &QListSpecialMethods::replaceInStrings(const QRegularExpression &rx, const QString &after) { QtPrivate::QStringList_replaceInStrings(self(), rx, after); @@ -297,8 +290,7 @@ inline int QStringList::lastIndexOf(const QRegularExpression &rx, int from) cons { return QtPrivate::QStringList_lastIndexOf(this, rx, from); } -#endif // QT_NO_REGULAREXPRESSION -#endif // QT_BOOTSTRAPPED +#endif // QT_CONFIG(regularexpression) #endif // Q_QDOC QT_END_NAMESPACE -- cgit v1.2.3