Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_texture_tile_info_pool.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#ifndef __KIS_TEXTURE_TILE_INFO_POOL_H
8#define __KIS_TEXTURE_TILE_INFO_POOL_H
9
10#include <boost/pool/pool.hpp>
11#include <QtGlobal>
12#include <QVector>
13
14#include <QMutex>
15#include <QMutexLocker>
16#include <QSharedPointer>
17#include <QApplication>
18
19#include "kis_assert.h"
20#include "kis_debug.h"
21#include "kis_global.h"
23
24#include "kritaui_export.h"
25
26const int minPoolChunk = 32; // 8 MiB (default, with tilesize 256)
27const int maxPoolChunk = 128; // 32 MiB (default, with tilesize 256)
28const int freeThreshold = 64; // 16 MiB (default, with tilesize 256)
29
30
43{
44public:
45 KisTextureTileInfoPoolSingleSize(int tileWidth, int tileHeight, int pixelSize)
46 : m_chunkSize(tileWidth * tileHeight * pixelSize),
47 m_pool(m_chunkSize, minPoolChunk, maxPoolChunk),
48 m_numAllocations(0),
49 m_maxAllocations(0),
50 m_numFrees(0)
51 {
52 }
53
54 quint8* malloc() {
55 m_numAllocations++;
56 m_maxAllocations = qMax(m_maxAllocations, m_numAllocations);
57
58 return (quint8*)m_pool.malloc();
59 }
60
61 bool free(quint8 *ptr) {
62 m_numAllocations--;
63 m_numFrees++;
64 m_pool.free(ptr);
65
66 KIS_ASSERT_RECOVER_NOOP(m_numAllocations >= 0);
67
68 return !m_numAllocations && m_maxAllocations > freeThreshold;
69 }
70
71 int chunkSize() const {
72 return m_chunkSize;
73 }
74
75 int numFrees() const {
76 return m_numFrees;
77 }
78
79 void tryPurge(int numFrees) {
80 // checking numFrees here is asserting that there were no frees
81 // between the time we originally indicated the purge and now.
82 if (numFrees == m_numFrees && !m_numAllocations) {
83 m_pool.purge_memory();
84 m_maxAllocations = 0;
85 }
86 }
87
88private:
89 const int m_chunkSize;
90 boost::pool<boost::default_user_allocator_new_delete> m_pool;
94};
95
97
98class KRITAUI_EXPORT KisTextureTileInfoPoolWorker : public QObject
99{
100 Q_OBJECT
101public:
103
104public Q_SLOTS:
105 void slotPurge(int pixelSize, int numFrees);
106 void slotDelayedPurge();
107
108private:
111 QMap<int, int> m_purge;
112};
113
119class KRITAUI_EXPORT KisTextureTileInfoPool : public QObject
120{
121 Q_OBJECT
122public:
123 KisTextureTileInfoPool(int tileWidth, int tileHeight)
124 : m_tileWidth(tileWidth),
125 m_tileHeight(tileHeight)
126 {
127 m_worker = new KisTextureTileInfoPoolWorker(this);
128 m_worker->moveToThread(QApplication::instance()->thread());
129 connect(this, SIGNAL(purge(int, int)), m_worker, SLOT(slotPurge(int, int)));
130 }
131
133 delete m_worker;
134 qDeleteAll(m_pools);
135 }
136
140 quint8* malloc(int pixelSize) {
141 QMutexLocker l(&m_mutex);
142
143 if (m_pools.size() <= pixelSize) {
144 m_pools.resize(pixelSize + 1);
145 }
146
147 if (!m_pools[pixelSize]) {
148 m_pools[pixelSize] =
149 new KisTextureTileInfoPoolSingleSize(m_tileWidth, m_tileHeight, pixelSize);
150 }
151
152 return m_pools[pixelSize]->malloc();
153 }
154
158 void free(quint8 *ptr, int pixelSize) {
159 QMutexLocker l(&m_mutex);
160 KisTextureTileInfoPoolSingleSize *pool = m_pools[pixelSize];
161 if (pool->free(ptr)) {
162 Q_EMIT purge(pixelSize, pool->numFrees());
163 }
164 }
165
169 int chunkSize(int pixelSize) const {
170 QMutexLocker l(&m_mutex);
171 return m_pools[pixelSize]->chunkSize();
172 }
173
174 void tryPurge(int pixelSize, int numFrees) {
175 QMutexLocker l(&m_mutex);
176 m_pools[pixelSize]->tryPurge(numFrees);
177 }
178
179Q_SIGNALS:
180 void purge(int pixelSize, int numFrees);
181
182private:
183 mutable QMutex m_mutex;
184 const int m_tileWidth;
185 const int m_tileHeight;
188};
189
191
193{
195 typedef QPair<int, int> PoolId;
196
197public:
198 KisTextureTileInfoPoolSP getPool(int tileWidth, int tileHeight) {
199 QMutexLocker l(&m_mutex);
200
201 PoolId id(tileWidth, tileHeight);
202
204 m_storage[id].toStrongRef();
205
206 if (!pool) {
207 pool = toQShared(
208 new KisTextureTileInfoPool(tileWidth, tileHeight));
209 m_storage[id] = pool;
210 }
211
212 return pool;
213 }
214
215private:
216 QMutex m_mutex;
217 QHash<PoolId, KisTextureTileInfoPoolWSP> m_storage;
218};
219
220
221#endif /* __KIS_TEXTURE_TILE_INFO_POOL_H */
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
QWeakPointer< KisTextureTileInfoPool > KisTextureTileInfoPoolWSP
KisTextureTileInfoPoolSP getPool(int tileWidth, int tileHeight)
QHash< PoolId, KisTextureTileInfoPoolWSP > m_storage
KisTextureTileInfoPoolSingleSize(int tileWidth, int tileHeight, int pixelSize)
boost::pool< boost::default_user_allocator_new_delete > m_pool
void tryPurge(int pixelSize, int numFrees)
KisTextureTileInfoPool(int tileWidth, int tileHeight)
int chunkSize(int pixelSize) const
void free(quint8 *ptr, int pixelSize)
KisTextureTileInfoPoolWorker * m_worker
void purge(int pixelSize, int numFrees)
QVector< KisTextureTileInfoPoolSingleSize * > m_pools
#define KIS_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:97
QSharedPointer< T > toQShared(T *ptr)
const int minPoolChunk
const int maxPoolChunk
QSharedPointer< KisTextureTileInfoPool > KisTextureTileInfoPoolSP
const int freeThreshold