QtBase  v6.3.1
qfreelist_p.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QFREELIST_P_H
41 #define QFREELIST_P_H
42 
43 //
44 // W A R N I N G
45 // -------------
46 //
47 // This file is not part of the Qt API. It exists purely as an
48 // implementation detail. This header file may change from version to
49 // version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include <QtCore/private/qglobal_p.h>
55 #include <QtCore/qatomic.h>
56 
58 
67 template <typename T>
69 {
70  typedef const T &ConstReferenceType;
71  typedef T &ReferenceType;
72 
73  T _t;
75 
76  inline ConstReferenceType t() const { return _t; }
77  inline ReferenceType t() { return _t; }
78 };
79 
85 template <>
87 {
88  typedef void ConstReferenceType;
89  typedef void ReferenceType;
90 
92 
93  inline void t() const { }
94  inline void t() { }
95 };
96 
115 {
116  // used by QFreeList, make sure to define all of when customizing
117  enum {
118  InitialNextValue = 0,
119  IndexMask = 0x00ffffff,
120  SerialMask = ~IndexMask & ~0x80000000,
121  SerialCounter = IndexMask + 1,
122  MaxIndex = IndexMask,
123  BlockCount = 4
124  };
125 
126  static const int Sizes[BlockCount];
127 };
128 
146 template <typename T, typename ConstantsType = QFreeListDefaultConstants>
148 {
149  typedef T ValueType;
152  typedef typename ElementType::ReferenceType ReferenceType;
153 
154  // return which block the index \a x falls in, and modify \a x to be the index into that block
155  static inline int blockfor(int &x)
156  {
157  for (int i = 0; i < ConstantsType::BlockCount; ++i) {
158  int size = ConstantsType::Sizes[i];
159  if (x < size)
160  return i;
161  x -= size;
162  }
163  Q_UNREACHABLE();
164  return -1;
165  }
166 
167  // allocate a block of the given \a size, initialized starting with the given \a offset
168  static inline ElementType *allocate(int offset, int size)
169  {
170  // qDebug("QFreeList: allocating %d elements (%ld bytes) with offset %d", size, size * sizeof(ElementType), offset);
171  ElementType *v = new ElementType[size];
172  for (int i = 0; i < size; ++i)
173  v[i].next.storeRelaxed(offset + i + 1);
174  return v;
175  }
176 
177  // take the current serial number from \a o, increment it, and store it in \a n
178  static inline int incrementserial(int o, int n)
179  {
180  return int((uint(n) & ConstantsType::IndexMask) | ((uint(o) + ConstantsType::SerialCounter) & ConstantsType::SerialMask));
181  }
182 
183  // the blocks
184  QAtomicPointer<ElementType> _v[ConstantsType::BlockCount];
185  // the next free id
186  QAtomicInt _next;
187 
188  // QFreeList is not copyable
190 
191 public:
192  constexpr inline QFreeList();
193  inline ~QFreeList();
194 
195  // returns the payload for the given index \a x
196  inline ConstReferenceType at(int x) const;
197  inline ReferenceType operator[](int x);
198 
199  /*
200  Return the next free id. Use this id to access the payload (see above).
201  Call release(id) when done using the id.
202  */
203  inline int next();
204  inline void release(int id);
205 };
206 
207 template <typename T, typename ConstantsType>
209  :
210  _v{}, // uniform initialization required
211  _next(ConstantsType::InitialNextValue)
212 { }
213 
214 template <typename T, typename ConstantsType>
216 {
217  for (int i = 0; i < ConstantsType::BlockCount; ++i)
218  delete [] _v[i].loadAcquire();
219 }
220 
221 template <typename T, typename ConstantsType>
223 {
224  const int block = blockfor(x);
225  return (_v[block].loadRelaxed())[x].t();
226 }
227 
228 template <typename T, typename ConstantsType>
230 {
231  const int block = blockfor(x);
232  return (_v[block].loadRelaxed())[x].t();
233 }
234 
235 template <typename T, typename ConstantsType>
237 {
238  int id, newid, at;
239  ElementType *v;
240  do {
241  id = _next.loadAcquire();
242 
243  at = id & ConstantsType::IndexMask;
244  const int block = blockfor(at);
245  v = _v[block].loadAcquire();
246 
247  if (!v) {
248  v = allocate((id & ConstantsType::IndexMask) - at, ConstantsType::Sizes[block]);
249  if (!_v[block].testAndSetRelease(nullptr, v)) {
250  // race with another thread lost
251  delete[] v;
252  v = _v[block].loadAcquire();
253  Q_ASSERT(v != nullptr);
254  }
255  }
256 
257  newid = v[at].next.loadRelaxed() | (id & ~ConstantsType::IndexMask);
258  } while (!_next.testAndSetRelease(id, newid));
259  // qDebug("QFreeList::next(): returning %d (_next now %d, serial %d)",
260  // id & ConstantsType::IndexMask,
261  // newid & ConstantsType::IndexMask,
262  // (newid & ~ConstantsType::IndexMask) >> 24);
263  return id & ConstantsType::IndexMask;
264 }
265 
266 template <typename T, typename ConstantsType>
268 {
269  int at = id & ConstantsType::IndexMask;
270  const int block = blockfor(at);
271  ElementType *v = _v[block].loadRelaxed();
272 
273  int x, newid;
274  do {
275  x = _next.loadAcquire();
276  v[at].next.storeRelaxed(x & ConstantsType::IndexMask);
277 
278  newid = incrementserial(x, id);
279  } while (!_next.testAndSetRelease(x, newid));
280  // qDebug("QFreeList::release(%d): _next now %d (was %d), serial %d",
281  // id & ConstantsType::IndexMask,
282  // newid & ConstantsType::IndexMask,
283  // x & ConstantsType::IndexMask,
284  // (newid & ~ConstantsType::IndexMask) >> 24);
285 }
286 
288 
289 #endif // QFREELIST_P_H
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
The QAtomicInt class provides platform-independent atomic operations on int.
Definition: qatomic.h:158
The QAtomicPointer class is a template class that provides platform-independent atomic operations on ...
Definition: qatomic.h:172
ReferenceType operator[](int x)
Definition: qfreelist_p.h:229
ConstReferenceType at(int x) const
Definition: qfreelist_p.h:222
int next()
Definition: qfreelist_p.h:236
constexpr QFreeList()
Definition: qfreelist_p.h:208
void release(int id)
Definition: qfreelist_p.h:267
JOCTET JCOEFPTR block
Definition: jsimd.h:109
void
Definition: png.h:1080
#define Q_UNREACHABLE()
#define Q_DISABLE_COPY_MOVE(Class)
Definition: qglobal.h:519
#define Q_AUTOTEST_EXPORT
Definition: qglobal.h:579
unsigned int uint
Definition: qglobal.h:334
GLenum GLuint id
[6]
Definition: qopengl.h:270
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLintptr offset
GLfloat n
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
QAction * at
ReferenceType t()
Definition: qfreelist_p.h:77
QAtomicInt next
Definition: qfreelist_p.h:74
const T & ConstReferenceType
Definition: qfreelist_p.h:70
ConstReferenceType t() const
Definition: qfreelist_p.h:76
Definition: main.cpp:38