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// Qt-Security score:significant reason:default
5
6#ifndef QARRAYDATA_H
7#define QARRAYDATA_H
8
9#include <QtCore/qpair.h>
10#include <QtCore/qatomic.h>
11#include <QtCore/qflags.h>
12#include <QtCore/qcontainerfwd.h>
13#include <string.h>
14
15QT_BEGIN_NAMESPACE
16
17#if __has_cpp_attribute(gnu::malloc)
18# define Q_DECL_MALLOCLIKE [[nodiscard, gnu::malloc]]
19#elif Q_CC_MSVC_ONLY
20# define Q_DECL_MALLOCLIKE [[nodiscard]] __declspec(allocator) __declspec(restrict)
21#else
22# define Q_DECL_MALLOCLIKE [[nodiscard]]
23#endif
24
25template <class T> struct QTypedArrayData;
26
27template <class T>
29{
31 T *ptr;
32
33 [[deprecated]]
34 operator std::pair<QTypedArrayData<T>*, T*>() const noexcept { return {header, ptr}; }
35};
36
38{
43
48
51 CapacityReserved = 0x1 //!< the capacity was reserved by the user, try to keep it
52 };
53 Q_DECLARE_FLAGS(ArrayOptions, ArrayOption)
54
58
60 {
61 qsizetype a = alloc;
62 Q_PRESUME(a > 0);
63 return a;
64 }
65
67 {
68 qsizetype a = alloc;
69 Q_PRESUME(a > 0);
70 return a;
71 }
72
73 /// Returns true if sharing took place
74 bool ref() noexcept
75 {
76 ref_.refRelaxed(); // suffices for ref-counting
77 return true;
78 }
79
80 /// Returns false if deallocation is necessary
81 bool deref() noexcept
82 {
83 return ref_.deref();
84 }
85
86 bool isShared() const noexcept
87 {
88 return ref_.loadRelaxed() != 1;
89 }
90
91 // Returns true if a detach is necessary before modifying the data
92 // This method is intentionally not const: if you want to know whether
93 // detaching is necessary, you should be in a non-const function already
94 bool needsDetach() noexcept
95 {
96 return ref_.loadRelaxed() > 1;
97 }
98
99 qsizetype detachCapacity(qsizetype newSize) const noexcept
100 {
101 if (flags & CapacityReserved && newSize < constAllocatedCapacity())
102 return constAllocatedCapacity();
103 return newSize;
104 }
105
107 static Q_CORE_EXPORT void *allocate(QArrayData **pdata, qsizetype objectSize, qsizetype alignment,
108 qsizetype capacity, AllocationOption option = QArrayData::KeepSize) noexcept;
110 static Q_CORE_EXPORT void *allocate1(QArrayData **pdata, qsizetype capacity,
111 AllocationOption option = QArrayData::KeepSize) noexcept;
113 static Q_CORE_EXPORT void *allocate2(QArrayData **pdata, qsizetype capacity,
114 AllocationOption option = QArrayData::KeepSize) noexcept;
115
118 static Q_CORE_EXPORT void deallocate(QArrayData *data, qsizetype objectSize,
119 qsizetype alignment) noexcept;
120};
121
122Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::ArrayOptions)
123
124namespace QtPrivate {
125// QArrayData with strictest alignment requirements supported by malloc()
126#if defined(Q_PROCESSOR_X86_32) && defined(Q_CC_GNU)
127// GCC's definition is incorrect since GCC 8 (commit r240248 in SVN; commit
128// 63012d9a57edc950c5f30242d1e19318b5708060 in Git). This is applied to all
129// GCC-like compilers in case they decide to follow GCC's lead in being wrong.
130constexpr size_t MaxPrimitiveAlignment = 2 * sizeof(void *);
131#else
133#endif
134
138}
139
140template <class T>
141struct QTypedArrayData
142 : QArrayData
143{
145
146 [[nodiscard]] static QTypedArrayAllocationResult<T>
147 allocate(qsizetype capacity, AllocationOption option = QArrayData::KeepSize)
148 {
149 static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
150 Q_DECL_UNINITIALIZED
151 QArrayData *d;
152 void *result;
153 if constexpr (sizeof(T) == 1) {
154 // necessarily, alignof(T) == 1
155 result = allocate1(&d, capacity, option);
156 } else if constexpr (sizeof(T) == 2) {
157 // alignof(T) may be 1, but that makes no difference
158 result = allocate2(&d, capacity, option);
159 } else {
160 result = QArrayData::allocate(&d, sizeof(T), alignof(AlignmentDummy), capacity, option);
161 }
162#if __has_builtin(__builtin_assume_aligned)
163 // and yet we do offer results that have stricter alignment
164 result = __builtin_assume_aligned(result, Q_ALIGNOF(AlignmentDummy));
165#endif
166 return {static_cast<QTypedArrayData *>(d), static_cast<T *>(result)};
167 }
168
170 reallocateUnaligned(QTypedArrayData *data, T *dataPointer, qsizetype capacity, AllocationOption option)
171 {
172 static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
173 std::pair<QArrayData *, void *> pair =
174 QArrayData::reallocateUnaligned(data, dataPointer, sizeof(T), capacity, option);
175 return {static_cast<QTypedArrayData *>(pair.first), static_cast<T *>(pair.second)};
176 }
177
178 static void deallocate(QArrayData *data) noexcept
179 {
180 static_assert(sizeof(QTypedArrayData) == sizeof(QArrayData));
181 QArrayData::deallocate(data, sizeof(T), alignof(AlignmentDummy));
182 }
183
184 static T *dataStart(QArrayData *data, qsizetype alignment) noexcept
185 {
186 // Alignment is a power of two
187 Q_ASSERT(alignment >= qsizetype(alignof(QArrayData)) && !(alignment & (alignment - 1)));
188 void *start = reinterpret_cast<void *>((quintptr(data) + sizeof(QArrayData) + alignment - 1)
189 & ~quintptr(alignment - 1));
190 return static_cast<T *>(start);
191 }
192
193 constexpr static qsizetype maxSize() noexcept
194 {
195 // -1 to deal with the pointer one-past-the-end
196 return (QtPrivate::MaxAllocSize - sizeof(QtPrivate::AlignedQArrayData) - 1) / sizeof(T);
197 }
198 constexpr static qsizetype max_size() noexcept
199 {
200 return maxSize();
201 }
202};
203
204namespace QtPrivate {
205struct Q_CORE_EXPORT QContainerImplHelper
206{
209 {
212 if (position > originalLength) {
213 position = 0;
214 length = 0;
215 return Null;
216 }
217
218 if (position < 0) {
219 if (length < 0 || length + position >= originalLength) {
220 position = 0;
222 return Full;
223 }
224 if (length + position <= 0) {
225 position = length = 0;
226 return Null;
227 }
228 length += position;
229 position = 0;
230 } else if (size_t(length) > size_t(originalLength - position)) {
232 }
233
234 if (position == 0 && length == originalLength)
235 return Full;
236
237 return length > 0 ? Subset : Empty;
238 }
239};
240}
241
242#undef Q_DECL_MALLOCLIKE
243
244QT_END_NAMESPACE
245
246#endif // include guard
constexpr size_t MaxPrimitiveAlignment
Definition qarraydata.h:132
#define Q_DECL_MALLOCLIKE
Definition qarraydata.h:22
#define __has_builtin(x)
#define __has_cpp_attribute(x)
qsizetype detachCapacity(qsizetype newSize) const noexcept
Definition qarraydata.h:99
@ CapacityReserved
the capacity was reserved by the user, try to keep it
Definition qarraydata.h:51
@ ArrayOptionDefault
Definition qarraydata.h:50
bool deref() noexcept
Returns false if deallocation is necessary.
Definition qarraydata.h:81
ArrayOptions flags
Definition qarraydata.h:56
bool isShared() const noexcept
Definition qarraydata.h:86
qsizetype alloc
Definition qarraydata.h:57
qsizetype constAllocatedCapacity() const noexcept
Definition qarraydata.h:66
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:94
static Q_DECL_MALLOCLIKE Q_CORE_EXPORT void * allocate2(QArrayData **pdata, qsizetype capacity, AllocationOption option=QArrayData::KeepSize) noexcept
qsizetype allocatedCapacity() noexcept
Definition qarraydata.h:59
@ GrowsAtBeginning
Definition qarraydata.h:46
bool ref() noexcept
Returns true if sharing took place.
Definition qarraydata.h:74
static Q_DECL_MALLOCLIKE Q_CORE_EXPORT void * allocate1(QArrayData **pdata, qsizetype capacity, AllocationOption option=QArrayData::KeepSize) noexcept
QTypedArrayData< T > * header
Definition qarraydata.h:30
QtPrivate::AlignedQArrayData header
Definition qarraydata.h:144
static constexpr qsizetype maxSize() noexcept
Definition qarraydata.h:193
static constexpr qsizetype max_size() noexcept
Definition qarraydata.h:198
static void deallocate(QArrayData *data) noexcept
Definition qarraydata.h:178
static T * dataStart(QArrayData *data, qsizetype alignment) noexcept
Definition qarraydata.h:184
static QTypedArrayAllocationResult< T > allocate(qsizetype capacity, AllocationOption option=QArrayData::KeepSize)
Definition qarraydata.h:147
static QTypedArrayAllocationResult< T > reallocateUnaligned(QTypedArrayData *data, T *dataPointer, qsizetype capacity, AllocationOption option)
Definition qarraydata.h:170