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// Qt-Security score:significant
4
5#ifndef QRECYCLEPOOL_P_H
6#define QRECYCLEPOOL_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtCore/private/qglobal_p.h>
20
21#include <QtCore/q20memory.h>
22
23QT_BEGIN_NAMESPACE
24
25#define QRECYCLEPOOLCOOKIE 0x33218ADF
26
27template<typename T, int Step>
28class QRecyclePoolPrivate
29{
30public:
31 QRecyclePoolPrivate()
32 : recyclePoolHold(true), outstandingItems(0), cookie(QRECYCLEPOOLCOOKIE),
33 currentPage(nullptr), nextAllocated(nullptr)
34 {
35 }
36
37 bool recyclePoolHold;
38 int outstandingItems;
39 quint32 cookie;
40
41 struct PoolType : public T {
42 union {
43 QRecyclePoolPrivate<T, Step> *pool;
44 PoolType *nextAllocated;
45 };
46 };
47
48 struct Page {
49 Page *nextPage;
50 unsigned int free;
51 union {
52 char array[Step * sizeof(PoolType)];
53 qint64 q_for_alignment_1;
54 double q_for_alignment_2;
55 };
56 };
57
58 Page *currentPage;
59 PoolType *nextAllocated;
60
61 inline T *allocate();
62 static inline void dispose(T *);
63 inline void releaseIfPossible();
64};
65
66template<typename T, int Step = 1024>
68{
69public:
70 inline QRecyclePool();
71 inline ~QRecyclePool();
72
73 template<typename...Args>
74 [[nodiscard]] inline T *New(Args&&...args);
75
76 static inline void Delete(T *);
77
78private:
79 QRecyclePoolPrivate<T, Step> *d;
80};
81
82template<typename T, int Step>
84: d(new QRecyclePoolPrivate<T, Step>())
85{
86}
87
88template<typename T, int Step>
90{
91 d->recyclePoolHold = false;
92 d->releaseIfPossible();
93}
94
95template<typename T, int Step>
96template<typename...Args>
97T *QRecyclePool<T, Step>::New(Args&&...args)
98{
99 return q20::construct_at(d->allocate(), std::forward<Args>(args)...);
100}
101
102template<typename T, int Step>
103void QRecyclePool<T, Step>::Delete(T *t)
104{
105 t->~T();
106 QRecyclePoolPrivate<T, Step>::dispose(t);
107}
108
109template<typename T, int Step>
110void QRecyclePoolPrivate<T, Step>::releaseIfPossible()
111{
112 if (recyclePoolHold || outstandingItems)
113 return;
114
115 Page *p = currentPage;
116 while (p) {
117 Page *n = p->nextPage;
118 free(p);
119 p = n;
120 }
121
122 delete this;
123}
124
125template<typename T, int Step>
126T *QRecyclePoolPrivate<T, Step>::allocate()
127{
128 PoolType *rv = nullptr;
129 if (nextAllocated) {
130 rv = nextAllocated;
131 nextAllocated = rv->nextAllocated;
132 } else if (currentPage && currentPage->free) {
133 rv = (PoolType *)(currentPage->array + (Step - currentPage->free) * sizeof(PoolType));
134 currentPage->free--;
135 } else {
136 Page *p = (Page *)malloc(sizeof(Page));
137 p->nextPage = currentPage;
138 p->free = Step;
139 currentPage = p;
140
141 rv = (PoolType *)currentPage->array;
142 currentPage->free--;
143 }
144
145 rv->pool = this;
146 ++outstandingItems;
147 return rv;
148}
149
150template<typename T, int Step>
151void QRecyclePoolPrivate<T, Step>::dispose(T *t)
152{
153 PoolType *pt = static_cast<PoolType *>(t);
154 Q_ASSERT(pt->pool && pt->pool->cookie == QRECYCLEPOOLCOOKIE);
155
156 QRecyclePoolPrivate<T, Step> *This = pt->pool;
157 pt->nextAllocated = This->nextAllocated;
158 This->nextAllocated = pt;
159 --This->outstandingItems;
160 This->releaseIfPossible();
161}
162
163QT_END_NAMESPACE
164
165#endif // QRECYCLEPOOL_P_H
static void Delete(T *)
T * New(Args &&...args)
#define QRECYCLEPOOLCOOKIE