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