Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qfreelist_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QFREELIST_P_H
5#define QFREELIST_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/private/qglobal_p.h>
19#include <QtCore/qatomic.h>
20
22
31template <typename T>
33{
34 typedef const T &ConstReferenceType;
35 typedef T &ReferenceType;
36
37 T _t;
39
40 inline ConstReferenceType t() const { return _t; }
41 inline ReferenceType t() { return _t; }
42};
43
49template <>
51{
52 typedef void ConstReferenceType;
53 typedef void ReferenceType;
54
56
57 inline void t() const { }
58 inline void t() { }
59};
60
79{
80 // used by QFreeList, make sure to define all of when customizing
81 enum {
82 InitialNextValue = 0,
83 IndexMask = 0x00ffffff,
84 SerialMask = ~IndexMask & ~0x80000000,
85 SerialCounter = IndexMask + 1,
86 MaxIndex = IndexMask,
87 BlockCount = 4
88 };
89
90 static const int Sizes[BlockCount];
91};
92
110template <typename T, typename ConstantsType = QFreeListDefaultConstants>
112{
113 typedef T ValueType;
114 typedef QFreeListElement<T> ElementType;
115 typedef typename ElementType::ConstReferenceType ConstReferenceType;
116 typedef typename ElementType::ReferenceType ReferenceType;
117
118 // return which block the index \a x falls in, and modify \a x to be the index into that block
119 static inline int blockfor(int &x)
120 {
121 for (int i = 0; i < ConstantsType::BlockCount; ++i) {
122 int size = ConstantsType::Sizes[i];
123 if (x < size)
124 return i;
125 x -= size;
126 }
127 Q_UNREACHABLE_RETURN(-1);
128 }
129
130 // allocate a block of the given \a size, initialized starting with the given \a offset
131 static inline ElementType *allocate(int offset, int size)
132 {
133 // qDebug("QFreeList: allocating %d elements (%ld bytes) with offset %d", size, size * sizeof(ElementType), offset);
134 ElementType *v = new ElementType[size];
135 for (int i = 0; i < size; ++i)
136 v[i].next.storeRelaxed(offset + i + 1);
137 return v;
138 }
139
140 // take the current serial number from \a o, increment it, and store it in \a n
141 static inline int incrementserial(int o, int n)
142 {
143 return int((uint(n) & ConstantsType::IndexMask) | ((uint(o) + ConstantsType::SerialCounter) & ConstantsType::SerialMask));
144 }
145
146 // the blocks
147 QAtomicPointer<ElementType> _v[ConstantsType::BlockCount];
148 // the next free id
149 QAtomicInt _next;
150
151 // QFreeList is not copyable
152 Q_DISABLE_COPY_MOVE(QFreeList)
153
154public:
155 constexpr inline QFreeList();
156 inline ~QFreeList();
157
158 // returns the payload for the given index \a x
159 inline ConstReferenceType at(int x) const;
160 inline ReferenceType operator[](int x);
161
162 /*
163 Return the next free id. Use this id to access the payload (see above).
164 Call release(id) when done using the id.
165 */
166 inline int next();
167 inline void release(int id);
168};
169
170template <typename T, typename ConstantsType>
172 :
173 _v{}, // uniform initialization required
174 _next(ConstantsType::InitialNextValue)
175{ }
176
177template <typename T, typename ConstantsType>
179{
180 for (int i = 0; i < ConstantsType::BlockCount; ++i)
181 delete [] _v[i].loadAcquire();
182}
183
184template <typename T, typename ConstantsType>
185inline typename QFreeList<T, ConstantsType>::ConstReferenceType QFreeList<T, ConstantsType>::at(int x) const
186{
187 const int block = blockfor(x);
188 return (_v[block].loadRelaxed())[x].t();
189}
190
191template <typename T, typename ConstantsType>
192inline typename QFreeList<T, ConstantsType>::ReferenceType QFreeList<T, ConstantsType>::operator[](int x)
193{
194 const int block = blockfor(x);
195 return (_v[block].loadRelaxed())[x].t();
196}
197
198template <typename T, typename ConstantsType>
200{
201 int id, newid, at;
202 ElementType *v;
203 do {
204 id = _next.loadAcquire();
205
206 at = id & ConstantsType::IndexMask;
207 const int block = blockfor(at);
208 v = _v[block].loadAcquire();
209
210 if (!v) {
211 v = allocate((id & ConstantsType::IndexMask) - at, ConstantsType::Sizes[block]);
212 if (!_v[block].testAndSetRelease(nullptr, v)) {
213 // race with another thread lost
214 delete[] v;
215 v = _v[block].loadAcquire();
216 Q_ASSERT(v != nullptr);
217 }
218 }
219
220 newid = v[at].next.loadRelaxed() | (id & ~ConstantsType::IndexMask);
221 } while (!_next.testAndSetRelease(id, newid));
222 // qDebug("QFreeList::next(): returning %d (_next now %d, serial %d)",
223 // id & ConstantsType::IndexMask,
224 // newid & ConstantsType::IndexMask,
225 // (newid & ~ConstantsType::IndexMask) >> 24);
226 return id & ConstantsType::IndexMask;
227}
228
229template <typename T, typename ConstantsType>
231{
232 int at = id & ConstantsType::IndexMask;
233 const int block = blockfor(at);
234 ElementType *v = _v[block].loadRelaxed();
235
236 int x, newid;
237 do {
238 x = _next.loadAcquire();
239 v[at].next.storeRelaxed(x & ConstantsType::IndexMask);
240
241 newid = incrementserial(x, id);
242 } while (!_next.testAndSetRelease(x, newid));
243 // qDebug("QFreeList::release(%d): _next now %d (was %d), serial %d",
244 // id & ConstantsType::IndexMask,
245 // newid & ConstantsType::IndexMask,
246 // x & ConstantsType::IndexMask,
247 // (newid & ~ConstantsType::IndexMask) >> 24);
248}
249
251
252#endif // QFREELIST_P_H
\inmodule QtCore
Definition qatomic.h:112
ReferenceType operator[](int x)
ConstReferenceType at(int x) const
constexpr QFreeList()
void release(int id)
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint id
[7]
GLenum GLuint GLintptr offset
GLfloat n
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_AUTOTEST_EXPORT
unsigned int uint
Definition qtypes.h:34
sem release()
QAction * at
ReferenceType t()
Definition qfreelist_p.h:41
QAtomicInt next
Definition qfreelist_p.h:38
const T & ConstReferenceType
Definition qfreelist_p.h:34
ConstReferenceType t() const
Definition qfreelist_p.h:40