Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qarraydata.h
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2019 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QARRAYDATA_H
6#define QARRAYDATA_H
7
8#include <QtCore/qpair.h>
9#include <QtCore/qatomic.h>
10#include <QtCore/qflags.h>
11#include <QtCore/qcontainerfwd.h>
12#include <string.h>
13
14QT_BEGIN_NAMESPACE
15
16#if __has_cpp_attribute(gnu::malloc)
17# define Q_DECL_MALLOCLIKE [[nodiscard, gnu::malloc]]
18#elif Q_CC_MSVC_ONLY
19# define Q_DECL_MALLOCLIKE __declspec(allocator) __declspec(restrict) [[nodiscard]]
20#else
21# define Q_DECL_MALLOCLIKE [[nodiscard]]
22#endif
23
24template <class T> struct QTypedArrayData;
25
27{
32
37
40 CapacityReserved = 0x1 //!< the capacity was reserved by the user, try to keep it
41 };
42 Q_DECLARE_FLAGS(ArrayOptions, ArrayOption)
43
47
49 {
50 return alloc;
51 }
52
54 {
55 return alloc;
56 }
57
58 /// Returns true if sharing took place
59 bool ref() noexcept
60 {
61 ref_.ref();
62 return true;
63 }
64
65 /// Returns false if deallocation is necessary
66 bool deref() noexcept
67 {
68 return ref_.deref();
69 }
70
71 bool isShared() const noexcept
72 {
73 return ref_.loadRelaxed() != 1;
74 }
75
76 // Returns true if a detach is necessary before modifying the data
77 // This method is intentionally not const: if you want to know whether
78 // detaching is necessary, you should be in a non-const function already
79 bool needsDetach() noexcept
80 {
81 return ref_.loadRelaxed() > 1;
82 }
83
84 qsizetype detachCapacity(qsizetype newSize) const noexcept
85 {
86 if (flags & CapacityReserved && newSize < constAllocatedCapacity())
87 return constAllocatedCapacity();
88 return newSize;
89 }
90
92 static Q_CORE_EXPORT void *allocate(QArrayData **pdata, qsizetype objectSize, qsizetype alignment,
93 qsizetype capacity, AllocationOption option = QArrayData::KeepSize) noexcept;
95 static Q_CORE_EXPORT void *allocate1(QArrayData **pdata, qsizetype capacity,
96 AllocationOption option = QArrayData::KeepSize) noexcept;
98 static Q_CORE_EXPORT void *allocate2(QArrayData **pdata, qsizetype capacity,
99 AllocationOption option = QArrayData::KeepSize) noexcept;
100
103 static Q_CORE_EXPORT void deallocate(QArrayData *data, qsizetype objectSize,
104 qsizetype alignment) noexcept;
105};
106
107Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::ArrayOptions)
108
109namespace QtPrivate {
110// QArrayData with strictest alignment requirements supported by malloc()
111#if defined(Q_PROCESSOR_X86_32) && defined(Q_CC_GNU)
112// GCC's definition is incorrect since GCC 8 (commit r240248 in SVN; commit
113// 63012d9a57edc950c5f30242d1e19318b5708060 in Git). This is applied to all
114// GCC-like compilers in case they decide to follow GCC's lead in being wrong.
115constexpr size_t MaxPrimitiveAlignment = 2 * sizeof(void *);
116#else
118#endif
119
123}
124
125template <class T>
126struct QTypedArrayData
127 : QArrayData
128{
130
131 [[nodiscard]] static std::pair<QTypedArrayData *, T *> allocate(qsizetype capacity, AllocationOption option = QArrayData::KeepSize)
132 {
133 static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
134 QArrayData *d;
135 void *result;
136 if constexpr (sizeof(T) == 1) {
137 // necessarily, alignof(T) == 1
138 result = allocate1(&d, capacity, option);
139 } else if constexpr (sizeof(T) == 2) {
140 // alignof(T) may be 1, but that makes no difference
141 result = allocate2(&d, capacity, option);
142 } else {
143 result = QArrayData::allocate(&d, sizeof(T), alignof(AlignmentDummy), capacity, option);
144 }
145#if __has_builtin(__builtin_assume_aligned)
146 // and yet we do offer results that have stricter alignment
147 result = __builtin_assume_aligned(result, Q_ALIGNOF(AlignmentDummy));
148#endif
149 return {static_cast<QTypedArrayData *>(d), static_cast<T *>(result)};
150 }
151
152 static std::pair<QTypedArrayData *, T *>
153 reallocateUnaligned(QTypedArrayData *data, T *dataPointer, qsizetype capacity, AllocationOption option)
154 {
155 static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
156 std::pair<QArrayData *, void *> pair =
157 QArrayData::reallocateUnaligned(data, dataPointer, sizeof(T), capacity, option);
158 return {static_cast<QTypedArrayData *>(pair.first), static_cast<T *>(pair.second)};
159 }
160
161 static void deallocate(QArrayData *data) noexcept
162 {
163 static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
164 QArrayData::deallocate(data, sizeof(T), alignof(AlignmentDummy));
165 }
166
167 static T *dataStart(QArrayData *data, qsizetype alignment) noexcept
168 {
169 // Alignment is a power of two
170 Q_ASSERT(alignment >= qsizetype(alignof(QArrayData)) && !(alignment & (alignment - 1)));
171 void *start = reinterpret_cast<void *>(
172 (quintptr(data) + sizeof(QArrayData) + alignment - 1) & ~(alignment - 1));
173 return static_cast<T *>(start);
174 }
175
176 constexpr static qsizetype maxSize() noexcept
177 {
178 // -1 to deal with the pointer one-past-the-end
179 return (QtPrivate::MaxAllocSize - sizeof(QtPrivate::AlignedQArrayData) - 1) / sizeof(T);
180 }
181 constexpr static qsizetype max_size() noexcept
182 {
183 return maxSize();
184 }
185};
186
187namespace QtPrivate {
188struct Q_CORE_EXPORT QContainerImplHelper
189{
192 {
195 if (position > originalLength) {
196 position = 0;
197 length = 0;
198 return Null;
199 }
200
201 if (position < 0) {
202 if (length < 0 || length + position >= originalLength) {
203 position = 0;
205 return Full;
206 }
207 if (length + position <= 0) {
208 position = length = 0;
209 return Null;
210 }
211 length += position;
212 position = 0;
213 } else if (size_t(length) > size_t(originalLength - position)) {
215 }
216
217 if (position == 0 && length == originalLength)
218 return Full;
219
220 return length > 0 ? Subset : Empty;
221 }
222};
223}
224
225#undef Q_DECL_MALLOCLIKE
226
227QT_END_NAMESPACE
228
229#endif // include guard
constexpr size_t MaxPrimitiveAlignment
Definition qarraydata.h:117
#define Q_DECL_MALLOCLIKE
Definition qarraydata.h:21
#define __has_builtin(x)
#define __has_cpp_attribute(x)
qsizetype detachCapacity(qsizetype newSize) const noexcept
Definition qarraydata.h:84
@ CapacityReserved
the capacity was reserved by the user, try to keep it
Definition qarraydata.h:40
@ ArrayOptionDefault
Definition qarraydata.h:39
bool deref() noexcept
Returns false if deallocation is necessary.
Definition qarraydata.h:66
ArrayOptions flags
Definition qarraydata.h:45
bool isShared() const noexcept
Definition qarraydata.h:71
qsizetype alloc
Definition qarraydata.h:46
qsizetype constAllocatedCapacity() const noexcept
Definition qarraydata.h:53
static Q_DECL_MALLOCLIKE Q_CORE_EXPORT void * allocate(QArrayData **pdata, qsizetype objectSize, qsizetype alignment, qsizetype capacity, AllocationOption option=QArrayData::KeepSize) noexcept
static Q_CORE_EXPORT void deallocate(QArrayData *data, qsizetype objectSize, qsizetype alignment) noexcept
bool needsDetach() noexcept
Definition qarraydata.h:79
static Q_DECL_MALLOCLIKE Q_CORE_EXPORT void * allocate2(QArrayData **pdata, qsizetype capacity, AllocationOption option=QArrayData::KeepSize) noexcept
qsizetype allocatedCapacity() noexcept
Definition qarraydata.h:48
@ GrowsAtBeginning
Definition qarraydata.h:35
bool ref() noexcept
Returns true if sharing took place.
Definition qarraydata.h:59
static Q_DECL_MALLOCLIKE Q_CORE_EXPORT void * allocate1(QArrayData **pdata, qsizetype capacity, AllocationOption option=QArrayData::KeepSize) noexcept
QtPrivate::AlignedQArrayData header
Definition qarraydata.h:129
static std::pair< QTypedArrayData *, T * > reallocateUnaligned(QTypedArrayData *data, T *dataPointer, qsizetype capacity, AllocationOption option)
Definition qarraydata.h:153
static std::pair< QTypedArrayData *, T * > allocate(qsizetype capacity, AllocationOption option=QArrayData::KeepSize)
Definition qarraydata.h:131
static constexpr qsizetype maxSize() noexcept
Definition qarraydata.h:176
static constexpr qsizetype max_size() noexcept
Definition qarraydata.h:181
static void deallocate(QArrayData *data) noexcept
Definition qarraydata.h:161
static T * dataStart(QArrayData *data, qsizetype alignment) noexcept
Definition qarraydata.h:167