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
qrecyclepool_p.h
Go to the documentation of this file.
1// Copyright (C) 2021 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 QRECYCLEPOOL_P_H
5#define QRECYCLEPOOL_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
20#include <QtCore/q20memory.h>
21
22QT_BEGIN_NAMESPACE
23
24#define QRECYCLEPOOLCOOKIE 0x33218ADF
25
26template<typename T, int Step>
27class QRecyclePoolPrivate
28{
29public:
30 QRecyclePoolPrivate()
31 : recyclePoolHold(true), outstandingItems(0), cookie(QRECYCLEPOOLCOOKIE),
32 currentPage(nullptr), nextAllocated(nullptr)
33 {
34 }
35
36 bool recyclePoolHold;
37 int outstandingItems;
38 quint32 cookie;
39
40 struct PoolType : public T {
41 union {
42 QRecyclePoolPrivate<T, Step> *pool;
43 PoolType *nextAllocated;
44 };
45 };
46
47 struct Page {
48 Page *nextPage;
49 unsigned int free;
50 union {
51 char array[Step * sizeof(PoolType)];
52 qint64 q_for_alignment_1;
53 double q_for_alignment_2;
54 };
55 };
56
57 Page *currentPage;
58 PoolType *nextAllocated;
59
60 inline T *allocate();
61 static inline void dispose(T *);
62 inline void releaseIfPossible();
63};
64
65template<typename T, int Step = 1024>
67{
68public:
69 inline QRecyclePool();
70 inline ~QRecyclePool();
71
72 template<typename...Args>
73 [[nodiscard]] inline T *New(Args&&...args);
74
75 static inline void Delete(T *);
76
77private:
78 QRecyclePoolPrivate<T, Step> *d;
79};
80
81template<typename T, int Step>
83: d(new QRecyclePoolPrivate<T, Step>())
84{
85}
86
87template<typename T, int Step>
89{
90 d->recyclePoolHold = false;
91 d->releaseIfPossible();
92}
93
94template<typename T, int Step>
95template<typename...Args>
96T *QRecyclePool<T, Step>::New(Args&&...args)
97{
98 return q20::construct_at(d->allocate(), std::forward<Args>(args)...);
99}
100
101template<typename T, int Step>
102void QRecyclePool<T, Step>::Delete(T *t)
103{
104 t->~T();
105 QRecyclePoolPrivate<T, Step>::dispose(t);
106}
107
108template<typename T, int Step>
109void QRecyclePoolPrivate<T, Step>::releaseIfPossible()
110{
111 if (recyclePoolHold || outstandingItems)
112 return;
113
114 Page *p = currentPage;
115 while (p) {
116 Page *n = p->nextPage;
117 free(p);
118 p = n;
119 }
120
121 delete this;
122}
123
124template<typename T, int Step>
125T *QRecyclePoolPrivate<T, Step>::allocate()
126{
127 PoolType *rv = nullptr;
128 if (nextAllocated) {
129 rv = nextAllocated;
130 nextAllocated = rv->nextAllocated;
131 } else if (currentPage && currentPage->free) {
132 rv = (PoolType *)(currentPage->array + (Step - currentPage->free) * sizeof(PoolType));
133 currentPage->free--;
134 } else {
135 Page *p = (Page *)malloc(sizeof(Page));
136 p->nextPage = currentPage;
137 p->free = Step;
138 currentPage = p;
139
140 rv = (PoolType *)currentPage->array;
141 currentPage->free--;
142 }
143
144 rv->pool = this;
145 ++outstandingItems;
146 return rv;
147}
148
149template<typename T, int Step>
150void QRecyclePoolPrivate<T, Step>::dispose(T *t)
151{
152 PoolType *pt = static_cast<PoolType *>(t);
153 Q_ASSERT(pt->pool && pt->pool->cookie == QRECYCLEPOOLCOOKIE);
154
155 QRecyclePoolPrivate<T, Step> *This = pt->pool;
156 pt->nextAllocated = This->nextAllocated;
157 This->nextAllocated = pt;
158 --This->outstandingItems;
159 This->releaseIfPossible();
160}
161
162QT_END_NAMESPACE
163
164#endif // QRECYCLEPOOL_P_H
static void Delete(T *)
T * New(Args &&...args)
#define QRECYCLEPOOLCOOKIE