diff options
Diffstat (limited to 'src/corelib/tools/qarraydata.h')
-rw-r--r-- | src/corelib/tools/qarraydata.h | 114 |
1 files changed, 62 insertions, 52 deletions
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h index e4250cce47..da83fc1a21 100644 --- a/src/corelib/tools/qarraydata.h +++ b/src/corelib/tools/qarraydata.h @@ -1,52 +1,24 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Copyright (C) 2019 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$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// Copyright (C) 2019 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QARRAYDATA_H #define QARRAYDATA_H #include <QtCore/qpair.h> #include <QtCore/qatomic.h> +#include <QtCore/qflags.h> +#include <QtCore/qcontainerfwd.h> #include <string.h> QT_BEGIN_NAMESPACE +#if __has_cpp_attribute(gnu::malloc) +# define Q_DECL_MALLOCLIKE [[nodiscard, gnu::malloc]] +#else +# define Q_DECL_MALLOCLIKE [[nodiscard]] +#endif + template <class T> struct QTypedArrayData; struct QArrayData @@ -102,7 +74,7 @@ struct QArrayData // Returns true if a detach is necessary before modifying the data // This method is intentionally not const: if you want to know whether // detaching is necessary, you should be in a non-const function already - bool needsDetach() const noexcept + bool needsDetach() noexcept { return ref_.loadRelaxed() > 1; } @@ -114,13 +86,17 @@ struct QArrayData return newSize; } - [[nodiscard]] -#if defined(Q_CC_GNU) - __attribute__((__malloc__)) -#endif + Q_DECL_MALLOCLIKE static Q_CORE_EXPORT void *allocate(QArrayData **pdata, qsizetype objectSize, qsizetype alignment, qsizetype capacity, AllocationOption option = QArrayData::KeepSize) noexcept; - [[nodiscard]] static Q_CORE_EXPORT QPair<QArrayData *, void *> reallocateUnaligned(QArrayData *data, void *dataPointer, + Q_DECL_MALLOCLIKE + static Q_CORE_EXPORT void *allocate1(QArrayData **pdata, qsizetype capacity, + AllocationOption option = QArrayData::KeepSize) noexcept; + Q_DECL_MALLOCLIKE + static Q_CORE_EXPORT void *allocate2(QArrayData **pdata, qsizetype capacity, + AllocationOption option = QArrayData::KeepSize) noexcept; + + [[nodiscard]] static Q_CORE_EXPORT std::pair<QArrayData *, void *> reallocateUnaligned(QArrayData *data, void *dataPointer, qsizetype objectSize, qsizetype newCapacity, AllocationOption option) noexcept; static Q_CORE_EXPORT void deallocate(QArrayData *data, qsizetype objectSize, qsizetype alignment) noexcept; @@ -128,30 +104,56 @@ struct QArrayData Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::ArrayOptions) +namespace QtPrivate { +// QArrayData with strictest alignment requirements supported by malloc() +#if defined(Q_PROCESSOR_X86_32) && defined(Q_CC_GNU) +// GCC's definition is incorrect since GCC 8 (commit r240248 in SVN; commit +// 63012d9a57edc950c5f30242d1e19318b5708060 in Git). This is applied to all +// GCC-like compilers in case they decide to follow GCC's lead in being wrong. +constexpr size_t MaxPrimitiveAlignment = 2 * sizeof(void *); +#else +constexpr size_t MaxPrimitiveAlignment = alignof(std::max_align_t); +#endif + +struct alignas(MaxPrimitiveAlignment) AlignedQArrayData : QArrayData +{ +}; +} + template <class T> struct QTypedArrayData : QArrayData { - struct AlignmentDummy { QArrayData header; T data; }; + struct AlignmentDummy { QtPrivate::AlignedQArrayData header; T data; }; - [[nodiscard]] static QPair<QTypedArrayData *, T *> allocate(qsizetype capacity, AllocationOption option = QArrayData::KeepSize) + [[nodiscard]] static std::pair<QTypedArrayData *, T *> allocate(qsizetype capacity, AllocationOption option = QArrayData::KeepSize) { static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData)); QArrayData *d; - void *result = QArrayData::allocate(&d, sizeof(T), alignof(AlignmentDummy), capacity, option); + void *result; + if constexpr (sizeof(T) == 1) { + // necessarily, alignof(T) == 1 + result = allocate1(&d, capacity, option); + } else if constexpr (sizeof(T) == 2) { + // alignof(T) may be 1, but that makes no difference + result = allocate2(&d, capacity, option); + } else { + result = QArrayData::allocate(&d, sizeof(T), alignof(AlignmentDummy), capacity, option); + } #if __has_builtin(__builtin_assume_aligned) + // and yet we do offer results that have stricter alignment result = __builtin_assume_aligned(result, Q_ALIGNOF(AlignmentDummy)); #endif - return qMakePair(static_cast<QTypedArrayData *>(d), static_cast<T *>(result)); + return {static_cast<QTypedArrayData *>(d), static_cast<T *>(result)}; } - static QPair<QTypedArrayData *, T *> + static std::pair<QTypedArrayData *, T *> reallocateUnaligned(QTypedArrayData *data, T *dataPointer, qsizetype capacity, AllocationOption option) { static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData)); - QPair<QArrayData *, void *> pair = + std::pair<QArrayData *, void *> pair = QArrayData::reallocateUnaligned(data, dataPointer, sizeof(T), capacity, option); - return qMakePair(static_cast<QTypedArrayData *>(pair.first), static_cast<T *>(pair.second)); + return {static_cast<QTypedArrayData *>(pair.first), static_cast<T *>(pair.second)}; } static void deallocate(QArrayData *data) noexcept @@ -168,6 +170,12 @@ struct QTypedArrayData (quintptr(data) + sizeof(QArrayData) + alignment - 1) & ~(alignment - 1)); return static_cast<T *>(start); } + + constexpr static qsizetype max_size() noexcept + { + // -1 to deal with the pointer one-past-the-end + return (QtPrivate::MaxAllocSize - sizeof(QtPrivate::AlignedQArrayData) - 1) / sizeof(T); + } }; namespace QtPrivate { @@ -208,6 +216,8 @@ struct Q_CORE_EXPORT QContainerImplHelper }; } +#undef Q_DECL_MALLOCLIKE + QT_END_NAMESPACE #endif // include guard |