Krita Source Code Documentation
Loading...
Searching...
No Matches
KisTileDataPooler Class Reference

#include <kis_tile_data_pooler.h>

+ Inheritance diagram for KisTileDataPooler:

Public Member Functions

void forceUpdateMemoryStats ()
 
void kick ()
 
 KisTileDataPooler (KisTileDataStore *store, qint32 memoryLimit=-1)
 
qint64 lastHistoricalMemoryMetric () const
 
qint64 lastPoolMemoryMetric () const
 
qint64 lastRealMemoryMetric () const
 
void terminatePooler ()
 
void testingRereadConfig ()
 
 ~KisTileDataPooler () override
 

Protected Member Functions

qint32 canDonorMemory (KisTileData *td)
 
int clonesMetric (KisTileData *td)
 
int clonesMetric (KisTileData *td, int numClones)
 
void cloneTileData (KisTileData *td, qint32 numClones) const
 
template<class Iter >
void getLists (Iter *iter, QList< KisTileData * > &beggars, QList< KisTileData * > &donors, qint32 &memoryOccupied, qint32 &statRealMemory, qint32 &statHistoricalMemory)
 
qint32 needMemory (KisTileData *td)
 
qint32 numClonesNeeded (KisTileData *td) const
 
bool processLists (QList< KisTileData * > &beggars, QList< KisTileData * > &donors, qint32 &memoryOccupied)
 
void run () override
 
void tryFreeOrphanedClones (KisTileData *td)
 
qint32 tryGetMemory (QList< KisTileData * > &donors, qint32 memoryMetric)
 
void waitForWork ()
 

Protected Attributes

bool m_lastCycleHadWork
 
qint32 m_lastHistoricalMemoryMetric
 
qint32 m_lastPoolMemoryMetric
 
qint32 m_lastRealMemoryMetric
 
qint32 m_memoryLimit
 
QSemaphore m_semaphore
 
QAtomicInt m_shouldExitFlag
 
KisTileDataStorem_store
 
qint32 m_timeout
 

Static Protected Attributes

static const qint32 MAX_NUM_CLONES = 16
 
static const qint32 MAX_TIMEOUT = 60000
 
static const qint32 MIN_TIMEOUT = 100
 
static const qint32 TIMEOUT_FACTOR = 2
 

Private Member Functions

void debugTileStatistics ()
 

Detailed Description

Definition at line 19 of file kis_tile_data_pooler.h.

Constructor & Destructor Documentation

◆ KisTileDataPooler()

KisTileDataPooler::KisTileDataPooler ( KisTileDataStore * store,
qint32 memoryLimit = -1 )

Definition at line 80 of file kis_tile_data_pooler.cc.

81 : QThread()
82{
84 m_store = store;
86 m_lastCycleHadWork = false;
90
91 if(memoryLimit >= 0) {
92 m_memoryLimit = memoryLimit;
93 }
94 else {
95 m_memoryLimit = MiB_TO_METRIC(KisImageConfig(true).poolLimit());
96 }
97}
KisTileDataStore * m_store
static const qint32 MIN_TIMEOUT
T MiB_TO_METRIC(T value)

References m_lastCycleHadWork, m_lastHistoricalMemoryMetric, m_lastPoolMemoryMetric, m_lastRealMemoryMetric, m_memoryLimit, m_shouldExitFlag, m_store, m_timeout, MiB_TO_METRIC(), and MIN_TIMEOUT.

◆ ~KisTileDataPooler()

KisTileDataPooler::~KisTileDataPooler ( )
override

Definition at line 99 of file kis_tile_data_pooler.cc.

100{
101}

Member Function Documentation

◆ canDonorMemory()

qint32 KisTileDataPooler::canDonorMemory ( KisTileData * td)
inlineprotected

Definition at line 279 of file kis_tile_data_pooler.cc.

280{
281 return td->age() && clonesMetric(td);
282}
int clonesMetric(KisTileData *td, int numClones)
int age() const

References KisTileData::age(), and clonesMetric().

◆ clonesMetric() [1/2]

int KisTileDataPooler::clonesMetric ( KisTileData * td)
inlineprotected

Definition at line 260 of file kis_tile_data_pooler.cc.

260 {
261 return td->m_clonesStack.size() * td->pixelSize();
262}
quint32 pixelSize() const
KisTileDataCache m_clonesStack

References KisTileData::m_clonesStack, KisTileData::pixelSize(), and KisLocklessStack< T >::size().

◆ clonesMetric() [2/2]

int KisTileDataPooler::clonesMetric ( KisTileData * td,
int numClones )
inlineprotected

Definition at line 256 of file kis_tile_data_pooler.cc.

256 {
257 return numClones * td->pixelSize();
258}

References KisTileData::pixelSize().

◆ cloneTileData()

void KisTileDataPooler::cloneTileData ( KisTileData * td,
qint32 numClones ) const
protected

Definition at line 127 of file kis_tile_data_pooler.cc.

128{
129 if (numClones > 0) {
130 td->blockSwapping();
131 for (qint32 i = 0; i < numClones; i++) {
132 td->m_clonesStack.push(new KisTileData(*td, false));
133 }
134 td->unblockSwapping();
135 } else {
136 qint32 numUnneededClones = qAbs(numClones);
137 for (qint32 i = 0; i < numUnneededClones; i++) {
138 KisTileData *clone = 0;
139
140 bool result = td->m_clonesStack.pop(clone);
141 if(!result) break;
142
143 delete clone;
144 }
145 }
146
147 DEBUG_CLONE_ACTION(td, numClones);
148}
void unblockSwapping()
void blockSwapping()
#define DEBUG_CLONE_ACTION(td, numClones)

References KisTileData::blockSwapping(), DEBUG_CLONE_ACTION, KisTileData::m_clonesStack, KisLocklessStack< T >::pop(), KisLocklessStack< T >::push(), and KisTileData::unblockSwapping().

◆ debugTileStatistics()

void KisTileDataPooler::debugTileStatistics ( )
private

Assume we are called from the inside of the loop. This means m_store is already locked

Definition at line 388 of file kis_tile_data_pooler.cc.

389{
395 qint64 preallocatedTiles=0;
396
398 KisTileData *item;
399
400 while(iter->hasNext()) {
401 item = iter->next();
402 preallocatedTiles += item->m_clonesStack.size();
403 }
404
405 m_store->endIteration(iter);
406
407 dbgKrita << "Tiles statistics:\t total:" << m_store->numTiles() << "\t preallocated:"<< preallocatedTiles;
408}
void endIteration(KisTileDataStoreIterator *iterator)
KisTileDataStoreIterator * beginIteration()
qint32 numTiles() const
#define dbgKrita
Definition kis_debug.h:45

References KisTileDataStore::beginIteration(), dbgKrita, KisTileDataStore::endIteration(), KisTileDataStoreIterator::hasNext(), KisTileData::m_clonesStack, m_store, KisTileDataStoreIterator::next(), KisTileDataStore::numTiles(), and KisLocklessStack< T >::size().

◆ forceUpdateMemoryStats()

void KisTileDataPooler::forceUpdateMemoryStats ( )

Is case the pooler thread is not running, the user might force recalculation of the memory statistics explicitly.

Definition at line 216 of file kis_tile_data_pooler.cc.

217{
218 KIS_SAFE_ASSERT_RECOVER_RETURN(!isRunning());
219
221 QList<KisTileData*> beggars;
222 QList<KisTileData*> donors;
223 qint32 memoryOccupied;
224
225 qint32 statRealMemory;
226 qint32 statHistoricalMemory;
227
228
229 getLists(iter, beggars, donors,
230 memoryOccupied,
231 statRealMemory,
232 statHistoricalMemory);
233
234 m_lastPoolMemoryMetric = memoryOccupied;
235 m_lastRealMemoryMetric = statRealMemory;
236 m_lastHistoricalMemoryMetric = statHistoricalMemory;
237
238 m_store->endIteration(iter);
239}
void getLists(Iter *iter, QList< KisTileData * > &beggars, QList< KisTileData * > &donors, qint32 &memoryOccupied, qint32 &statRealMemory, qint32 &statHistoricalMemory)
KisTileDataStoreReverseIterator * beginReverseIteration()
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128

References KisTileDataStore::beginReverseIteration(), KisTileDataStore::endIteration(), getLists(), KIS_SAFE_ASSERT_RECOVER_RETURN, m_lastHistoricalMemoryMetric, m_lastPoolMemoryMetric, m_lastRealMemoryMetric, and m_store.

◆ getLists()

template<class Iter >
void KisTileDataPooler::getLists ( Iter * iter,
QList< KisTileData * > & beggars,
QList< KisTileData * > & donors,
qint32 & memoryOccupied,
qint32 & statRealMemory,
qint32 & statHistoricalMemory )
protected

Definition at line 285 of file kis_tile_data_pooler.cc.

291{
292 memoryOccupied = 0;
293 statRealMemory = 0;
294 statHistoricalMemory = 0;
295
296 qint32 needMemoryTotal = 0;
297 qint32 canDonorMemoryTotal = 0;
298
299 qint32 neededMemory;
300 qint32 donoredMemory;
301
302 KisTileData *item;
303
304 while(iter->hasNext()) {
305 item = iter->next();
306
308
309 if((neededMemory = needMemory(item))) {
310 needMemoryTotal += neededMemory;
311 beggars.append(item);
312 }
313 else if((donoredMemory = canDonorMemory(item))) {
314 canDonorMemoryTotal += donoredMemory;
315 donors.append(item);
316 }
317
318 memoryOccupied += clonesMetric(item);
319
320 // statistics gathering
321 if (item->historical()) {
322 statHistoricalMemory += item->pixelSize();
323 } else {
324 statRealMemory += item->pixelSize();
325 }
326 }
327
328 DEBUG_LISTS(memoryOccupied,
329 beggars, needMemoryTotal,
330 donors, canDonorMemoryTotal);
331}
qint32 canDonorMemory(KisTileData *td)
void tryFreeOrphanedClones(KisTileData *td)
qint32 needMemory(KisTileData *td)
bool historical() const
#define DEBUG_LISTS(mem, beggars, beggarsMem, donors, donorsMem)

References canDonorMemory(), clonesMetric(), DEBUG_LISTS, KisTileData::historical(), needMemory(), KisTileData::pixelSize(), and tryFreeOrphanedClones().

◆ kick()

void KisTileDataPooler::kick ( )

Definition at line 103 of file kis_tile_data_pooler.cc.

104{
105 m_semaphore.release();
106}

References m_semaphore.

◆ lastHistoricalMemoryMetric()

qint64 KisTileDataPooler::lastHistoricalMemoryMetric ( ) const

Definition at line 251 of file kis_tile_data_pooler.cc.

252{
254}

References m_lastHistoricalMemoryMetric.

◆ lastPoolMemoryMetric()

qint64 KisTileDataPooler::lastPoolMemoryMetric ( ) const

Definition at line 241 of file kis_tile_data_pooler.cc.

242{
244}

References m_lastPoolMemoryMetric.

◆ lastRealMemoryMetric()

qint64 KisTileDataPooler::lastRealMemoryMetric ( ) const

Definition at line 246 of file kis_tile_data_pooler.cc.

247{
249}

References m_lastRealMemoryMetric.

◆ needMemory()

qint32 KisTileDataPooler::needMemory ( KisTileData * td)
inlineprotected

Definition at line 273 of file kis_tile_data_pooler.cc.

274{
275 qint32 clonesNeeded = !td->age() ? qMax(0, numClonesNeeded(td)) : 0;
276 return clonesMetric(td, clonesNeeded);
277}
qint32 numClonesNeeded(KisTileData *td) const

References KisTileData::age(), clonesMetric(), and numClonesNeeded().

◆ numClonesNeeded()

qint32 KisTileDataPooler::numClonesNeeded ( KisTileData * td) const
protected

Definition at line 117 of file kis_tile_data_pooler.cc.

118{
120 qint32 numUsers = td->m_usersCount;
121 qint32 numPresentClones = td->m_clonesStack.size();
122 qint32 totalClones = qMin(numUsers - 1, MAX_NUM_CLONES);
123
124 return totalClones - numPresentClones;
125}
static const qint32 MAX_NUM_CLONES
#define RUNTIME_SANITY_CHECK(td)

References KisTileData::m_clonesStack, KisTileData::m_usersCount, MAX_NUM_CLONES, RUNTIME_SANITY_CHECK, and KisLocklessStack< T >::size().

◆ processLists()

bool KisTileDataPooler::processLists ( QList< KisTileData * > & beggars,
QList< KisTileData * > & donors,
qint32 & memoryOccupied )
protected

Definition at line 354 of file kis_tile_data_pooler.cc.

357{
358 bool hadWork = false;
359
360
361 Q_FOREACH (KisTileData *item, beggars) {
362 qint32 clonesNeeded = numClonesNeeded(item);
363 qint32 clonesMemory = clonesMetric(item, clonesNeeded);
364
365 qint32 memoryLeft =
366 m_memoryLimit - (memoryOccupied + clonesMemory);
367
368 if(memoryLeft < 0) {
369 qint32 freedMemory = tryGetMemory(donors, -memoryLeft);
370 memoryOccupied -= freedMemory;
371
372 DEBUG_FREE_CLONE(freedMemory, memoryLeft);
373
374 if(m_memoryLimit < memoryOccupied + clonesMemory)
375 break;
376 }
377
378 cloneTileData(item, clonesNeeded);
379 DEBUG_ALLOC_CLONE(clonesMemory, memoryOccupied);
380
381 memoryOccupied += clonesMemory;
382 hadWork = true;
383 }
384
385 return hadWork;
386}
qint32 tryGetMemory(QList< KisTileData * > &donors, qint32 memoryMetric)
void cloneTileData(KisTileData *td, qint32 numClones) const
#define DEBUG_ALLOC_CLONE(mem, totalMem)
#define DEBUG_FREE_CLONE(freed, demanded)

References clonesMetric(), cloneTileData(), DEBUG_ALLOC_CLONE, DEBUG_FREE_CLONE, m_memoryLimit, numClonesNeeded(), and tryGetMemory().

◆ run()

void KisTileDataPooler::run ( )
overrideprotected

Definition at line 170 of file kis_tile_data_pooler.cc.

171{
172 if(!m_memoryLimit) return;
173
174 m_shouldExitFlag = false;
175
176 while (1) {
177 DEBUG_SIMPLE_ACTION("went to bed... Zzz...");
178
179 waitForWork();
180
182 break;
183
184 QThread::msleep(0);
185 DEBUG_SIMPLE_ACTION("cycle started");
186
187
189 QList<KisTileData*> beggars;
190 QList<KisTileData*> donors;
191 qint32 memoryOccupied;
192
193 qint32 statRealMemory;
194 qint32 statHistoricalMemory;
195
196
197 getLists(iter, beggars, donors,
198 memoryOccupied,
199 statRealMemory,
200 statHistoricalMemory);
201
203 processLists(beggars, donors, memoryOccupied);
204
205 m_lastPoolMemoryMetric = memoryOccupied;
206 m_lastRealMemoryMetric = statRealMemory;
207 m_lastHistoricalMemoryMetric = statHistoricalMemory;
208
209 m_store->endIteration(iter);
210
212 DEBUG_SIMPLE_ACTION("cycle finished");
213 }
214}
bool processLists(QList< KisTileData * > &beggars, QList< KisTileData * > &donors, qint32 &memoryOccupied)
#define DEBUG_TILE_STATISTICS()
#define DEBUG_SIMPLE_ACTION(action)

References KisTileDataStore::beginReverseIteration(), DEBUG_SIMPLE_ACTION, DEBUG_TILE_STATISTICS, KisTileDataStore::endIteration(), getLists(), m_lastCycleHadWork, m_lastHistoricalMemoryMetric, m_lastPoolMemoryMetric, m_lastRealMemoryMetric, m_memoryLimit, m_shouldExitFlag, m_store, processLists(), and waitForWork().

◆ terminatePooler()

void KisTileDataPooler::terminatePooler ( )

Definition at line 108 of file kis_tile_data_pooler.cc.

109{
110 unsigned long exitTimeout = 100;
111 do {
112 m_shouldExitFlag = true;
113 kick();
114 } while(!wait(exitTimeout));
115}

References kick(), and m_shouldExitFlag.

◆ testingRereadConfig()

void KisTileDataPooler::testingRereadConfig ( )

Definition at line 410 of file kis_tile_data_pooler.cc.

411{
412 m_memoryLimit = MiB_TO_METRIC(KisImageConfig(true).poolLimit());
413}

References m_memoryLimit, and MiB_TO_METRIC().

◆ tryFreeOrphanedClones()

void KisTileDataPooler::tryFreeOrphanedClones ( KisTileData * td)
inlineprotected

Definition at line 264 of file kis_tile_data_pooler.cc.

265{
266 qint32 extraClones = -numClonesNeeded(td);
267
268 if(extraClones > 0) {
269 cloneTileData(td, -extraClones);
270 }
271}

References cloneTileData(), and numClonesNeeded().

◆ tryGetMemory()

qint32 KisTileDataPooler::tryGetMemory ( QList< KisTileData * > & donors,
qint32 memoryMetric )
protected

Definition at line 333 of file kis_tile_data_pooler.cc.

335{
336 qint32 memoryFreed = 0;
337
338 QMutableListIterator<KisTileData*> iter(donors);
339 iter.toBack();
340
341 while(iter.hasPrevious() && memoryFreed < memoryMetric) {
342 KisTileData *item = iter.previous();
343
344 qint32 numClones = item->m_clonesStack.size();
345 cloneTileData(item, -numClones);
346 memoryFreed += clonesMetric(item, numClones);
347
348 iter.remove();
349 }
350
351 return memoryFreed;
352}

References clonesMetric(), cloneTileData(), KisTileData::m_clonesStack, and KisLocklessStack< T >::size().

◆ waitForWork()

void KisTileDataPooler::waitForWork ( )
protected

Definition at line 150 of file kis_tile_data_pooler.cc.

151{
152 bool success;
153
155 success = m_semaphore.tryAcquire(1, m_timeout);
156 else {
157 m_semaphore.acquire();
158 success = true;
159 }
160
161 m_lastCycleHadWork = false;
162 if (success) {
164 } else {
167 }
168}
static const qint32 TIMEOUT_FACTOR
static const qint32 MAX_TIMEOUT

References m_lastCycleHadWork, m_semaphore, m_timeout, MAX_TIMEOUT, MIN_TIMEOUT, and TIMEOUT_FACTOR.

Member Data Documentation

◆ m_lastCycleHadWork

bool KisTileDataPooler::m_lastCycleHadWork
protected

Definition at line 81 of file kis_tile_data_pooler.h.

◆ m_lastHistoricalMemoryMetric

qint32 KisTileDataPooler::m_lastHistoricalMemoryMetric
protected

Definition at line 85 of file kis_tile_data_pooler.h.

◆ m_lastPoolMemoryMetric

qint32 KisTileDataPooler::m_lastPoolMemoryMetric
protected

Definition at line 83 of file kis_tile_data_pooler.h.

◆ m_lastRealMemoryMetric

qint32 KisTileDataPooler::m_lastRealMemoryMetric
protected

Definition at line 84 of file kis_tile_data_pooler.h.

◆ m_memoryLimit

qint32 KisTileDataPooler::m_memoryLimit
protected

Definition at line 82 of file kis_tile_data_pooler.h.

◆ m_semaphore

QSemaphore KisTileDataPooler::m_semaphore
protected

Definition at line 77 of file kis_tile_data_pooler.h.

◆ m_shouldExitFlag

QAtomicInt KisTileDataPooler::m_shouldExitFlag
protected

Definition at line 78 of file kis_tile_data_pooler.h.

◆ m_store

KisTileDataStore* KisTileDataPooler::m_store
protected

Definition at line 79 of file kis_tile_data_pooler.h.

◆ m_timeout

qint32 KisTileDataPooler::m_timeout
protected

Definition at line 80 of file kis_tile_data_pooler.h.

◆ MAX_NUM_CLONES

const qint32 KisTileDataPooler::MAX_NUM_CLONES = 16
staticprotected

Definition at line 45 of file kis_tile_data_pooler.h.

◆ MAX_TIMEOUT

const qint32 KisTileDataPooler::MAX_TIMEOUT = 60000
staticprotected

Definition at line 46 of file kis_tile_data_pooler.h.

◆ MIN_TIMEOUT

const qint32 KisTileDataPooler::MIN_TIMEOUT = 100
staticprotected

Definition at line 47 of file kis_tile_data_pooler.h.

◆ TIMEOUT_FACTOR

const qint32 KisTileDataPooler::TIMEOUT_FACTOR = 2
staticprotected

Definition at line 48 of file kis_tile_data_pooler.h.


The documentation for this class was generated from the following files: