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

#include <kis_tile_data_store.h>

Classes

struct  MemoryStatistics
 

Public Member Functions

KisTileDataStoreClockIteratorbeginClockIteration ()
 
KisTileDataStoreIteratorbeginIteration ()
 
KisTileDataStoreReverseIteratorbeginReverseIteration ()
 
void checkFreeMemory ()
 
KisTileDatacreateDefaultTileData (qint32 pixelSize, const quint8 *defPixel)
 
void debugPrintList ()
 
KisTileDataduplicateTileData (KisTileData *rhs)
 
void endIteration (KisTileDataStoreClockIterator *iterator)
 
void endIteration (KisTileDataStoreIterator *iterator)
 
void endIteration (KisTileDataStoreReverseIterator *iterator)
 
void ensureTileDataLoaded (KisTileData *td)
 
void freeTileData (KisTileData *td)
 
void kickPooler ()
 
 KisTileDataStore ()
 
qint64 memoryMetric () const
 
MemoryStatistics memoryStatistics ()
 
qint32 numTiles () const
 
qint32 numTilesInMemory () const
 
void registerTileData (KisTileData *td)
 
void tryForceUpdateMemoryStatisticsWhileIdle ()
 
bool trySwapTileData (KisTileData *td)
 
void unregisterTileData (KisTileData *td)
 
 ~KisTileDataStore ()
 

Static Public Member Functions

static KisTileDataStoreinstance ()
 

Private Member Functions

KisTileDataallocTileData (qint32 pixelSize, const quint8 *defPixel)
 
void debugClear ()
 
void debugSwapAll ()
 
void freeRegisteredTiles ()
 
void registerTileDataImp (KisTileData *td)
 
void testingRereadConfig ()
 
void testingResumePooler ()
 
void testingSuspendPooler ()
 
void unregisterTileDataImp (KisTileData *td)
 

Private Attributes

QAtomicInt m_clockIndex
 
QAtomicInt m_counter
 
QReadWriteLock m_iteratorLock
 
QAtomicInt m_memoryMetric
 
QAtomicInt m_numTiles
 
KisTileDataPooler m_pooler
 
KisSwappedDataStore m_swappedStore
 
KisTileDataSwapper m_swapper
 
ConcurrentMap< int, KisTileData * > m_tileDataMap
 

Friends

class DeadlockyThread
 
class KisLowMemoryBenchmark
 
class KisLowMemoryTests
 
class KisTileDataPoolerTest
 
class KisTileDataStoreTest
 
class KisTiledDataManagerTest
 

Detailed Description

Stores tileData objects. When needed compresses them and swaps.

Definition at line 28 of file kis_tile_data_store.h.

Constructor & Destructor Documentation

◆ KisTileDataStore()

KisTileDataStore::KisTileDataStore ( )

Definition at line 58 of file kis_tile_data_store.cc.

59 : m_pooler(this),
60 m_swapper(this),
61 m_numTiles(0),
63 m_counter(1),
65{
66 m_pooler.start();
67 m_swapper.start();
68}
KisTileDataPooler m_pooler
KisTileDataSwapper m_swapper

References m_pooler, and m_swapper.

◆ ~KisTileDataStore()

KisTileDataStore::~KisTileDataStore ( )

Definition at line 70 of file kis_tile_data_store.cc.

71{
74
75 if (numTiles() > 0) {
76 errKrita << "Warning: some tiles have leaked:";
77 errKrita << "\tTiles in memory:" << numTilesInMemory() << "\n"
78 << "\tTotal tiles:" << numTiles();
79 }
80}
qint32 numTilesInMemory() const
qint32 numTiles() const
#define errKrita
Definition kis_debug.h:107

References errKrita, m_pooler, m_swapper, numTiles(), numTilesInMemory(), KisTileDataPooler::terminatePooler(), and KisTileDataSwapper::terminateSwapper().

Member Function Documentation

◆ allocTileData()

KisTileData * KisTileDataStore::allocTileData ( qint32 pixelSize,
const quint8 * defPixel )
private

Definition at line 167 of file kis_tile_data_store.cc.

168{
169 KisTileData *td = new KisTileData(pixelSize, defPixel, this);
171 return td;
172}
void registerTileData(KisTileData *td)

References registerTileData().

◆ beginClockIteration()

KisTileDataStoreClockIterator * KisTileDataStore::beginClockIteration ( )

Definition at line 305 of file kis_tile_data_store.cc.

306{
307 m_iteratorLock.lockForWrite();
308 return new KisTileDataStoreClockIterator(m_tileDataMap, m_clockIndex.loadAcquire(), this);
309}
QReadWriteLock m_iteratorLock
ConcurrentMap< int, KisTileData * > m_tileDataMap

References m_clockIndex, m_iteratorLock, and m_tileDataMap.

◆ beginIteration()

KisTileDataStoreIterator * KisTileDataStore::beginIteration ( )

Definition at line 282 of file kis_tile_data_store.cc.

References m_iteratorLock, and m_tileDataMap.

◆ beginReverseIteration()

KisTileDataStoreReverseIterator * KisTileDataStore::beginReverseIteration ( )

Definition at line 293 of file kis_tile_data_store.cc.

References m_iteratorLock, and m_tileDataMap.

◆ checkFreeMemory()

void KisTileDataStore::checkFreeMemory ( )
inline

Definition at line 67 of file kis_tile_data_store.h.

◆ createDefaultTileData()

KisTileData * KisTileDataStore::createDefaultTileData ( qint32 pixelSize,
const quint8 * defPixel )
inline

Definition at line 89 of file kis_tile_data_store.h.

90 {
91 return allocTileData(pixelSize, defPixel);
92 }
KisTileData * allocTileData(qint32 pixelSize, const quint8 *defPixel)

◆ debugClear()

void KisTileDataStore::debugClear ( )
private

◆ debugPrintList()

void KisTileDataStore::debugPrintList ( )

Definition at line 318 of file kis_tile_data_store.cc.

319{
321 KisTileData *item = 0;
322
323 while (iter->hasNext()) {
324 item = iter->next();
325 dbgTiles << "-------------------------\n"
326 << "TileData:\t\t\t" << item
327 << "\n refCount:\t" << item->m_refCount;
328 }
329
330 endIteration(iter);
331}
void endIteration(KisTileDataStoreIterator *iterator)
KisTileDataStoreIterator * beginIteration()
#define dbgTiles
Definition kis_debug.h:49

References beginIteration(), dbgTiles, endIteration(), KisTileDataStoreIterator::hasNext(), KisTileData::m_refCount, and KisTileDataStoreIterator::next().

◆ debugSwapAll()

void KisTileDataStore::debugSwapAll ( )
private

Definition at line 333 of file kis_tile_data_store.cc.

334{
336 KisTileData *item = 0;
337
338 while (iter->hasNext()) {
339 item = iter->next();
340 iter->trySwapOut(item);
341 }
342
343 endIteration(iter);
344
345// dbgKrita << "Number of tiles:" << numTiles();
346// dbgKrita << "Tiles in memory:" << numTilesInMemory();
347// m_swappedStore.debugStatistics();
348}

References beginIteration(), endIteration(), KisTileDataStoreIterator::hasNext(), KisTileDataStoreIterator::next(), and KisTileDataStoreIterator::trySwapOut().

◆ duplicateTileData()

KisTileData * KisTileDataStore::duplicateTileData ( KisTileData * rhs)

WARN: The following three method are only for usage in KisTileData. Do not call them directly!

Definition at line 174 of file kis_tile_data_store.cc.

175{
176 KisTileData *td = 0;
177
178 if (rhs->m_clonesStack.pop(td)) {
179 DEBUG_PRECLONE_ACTION("+ Pre-clone HIT", rhs, td);
181 } else {
182 rhs->blockSwapping();
183 td = new KisTileData(*rhs);
184 rhs->unblockSwapping();
185 DEBUG_PRECLONE_ACTION("- Pre-clone #MISS#", rhs, td);
187 }
188
190 return td;
191}
void unblockSwapping()
void blockSwapping()
KisTileDataCache m_clonesStack
#define DEBUG_COUNT_PRECLONE_HIT(td)
#define DEBUG_PRECLONE_ACTION(action, oldTD, newTD)
#define DEBUG_COUNT_PRECLONE_MISS(td)

References KisTileData::blockSwapping(), DEBUG_COUNT_PRECLONE_HIT, DEBUG_COUNT_PRECLONE_MISS, DEBUG_PRECLONE_ACTION, KisTileData::m_clonesStack, KisLocklessStack< T >::pop(), registerTileData(), and KisTileData::unblockSwapping().

◆ endIteration() [1/3]

void KisTileDataStore::endIteration ( KisTileDataStoreClockIterator * iterator)

Definition at line 311 of file kis_tile_data_store.cc.

312{
313 m_clockIndex = iterator->getFinalPosition();
314 delete iterator;
315 m_iteratorLock.unlock();
316}

References KisTileDataStoreClockIterator::getFinalPosition(), m_clockIndex, and m_iteratorLock.

◆ endIteration() [2/3]

void KisTileDataStore::endIteration ( KisTileDataStoreIterator * iterator)

Definition at line 287 of file kis_tile_data_store.cc.

288{
289 delete iterator;
290 m_iteratorLock.unlock();
291}

References m_iteratorLock.

◆ endIteration() [3/3]

void KisTileDataStore::endIteration ( KisTileDataStoreReverseIterator * iterator)

Definition at line 298 of file kis_tile_data_store.cc.

299{
300 delete iterator;
301 m_iteratorLock.unlock();
303}
#define DEBUG_REPORT_PRECLONE_EFFICIENCY()

References DEBUG_REPORT_PRECLONE_EFFICIENCY, and m_iteratorLock.

◆ ensureTileDataLoaded()

void KisTileDataStore::ensureTileDataLoaded ( KisTileData * td)

Ensures that the tile data is totally present in memory and it's swapping is blocked by holding td->m_swapLock in a read mode. PRECONDITIONS: td->m_swapLock is unlocked m_listRWLock is unlocked POSTCONDITIONS: td->m_data is in memory and td->m_swapLock is locked m_listRWLock is unlocked

The order of this heavy locking is very important. Change it only in case, you really know what you are doing.

If someone has managed to load the td from swap, then, most probably, they have already taken the swap lock. This may lead to a deadlock, because COW mechanism breaks lock ordering rules in duplicateTileData() (it takes m_listLock while the swap lock is held). In our case it is enough just to check whether the other thread has already fetched the data. Please notice that we do not take both of the locks while checking this, because holding m_listLock is enough. Nothing can happen to the tile while we hold m_listLock.

<– In theory, livelock is possible here...

Definition at line 214 of file kis_tile_data_store.cc.

215{
216// dbgKrita << "#### SWAP MISS! ####" << td << ppVar(td->mementoed()) << ppVar(td->age()) << ppVar(td->numUsers());
218
219 td->m_swapLock.lockForRead();
220
221 while (!td->data()) {
222 td->m_swapLock.unlock();
223
228 m_iteratorLock.lockForWrite();
229
243 if (!td->data()) {
244 td->m_swapLock.lockForWrite();
245
248
249 td->m_swapLock.unlock();
250 }
251
252 m_iteratorLock.unlock();
253
258 td->m_swapLock.lockForRead();
259 }
260}
void swapInTileData(KisTileData *td)
KisSwappedDataStore m_swappedStore
void registerTileDataImp(KisTileData *td)
QReadWriteLock m_swapLock
quint8 * data() const

References checkFreeMemory(), KisTileData::data(), m_iteratorLock, KisTileData::m_swapLock, m_swappedStore, registerTileDataImp(), and KisSwappedDataStore::swapInTileData().

◆ freeRegisteredTiles()

void KisTileDataStore::freeRegisteredTiles ( )
private

◆ freeTileData()

void KisTileDataStore::freeTileData ( KisTileData * td)

Definition at line 193 of file kis_tile_data_store.cc.

194{
195 Q_ASSERT(td->m_store == this);
196
198
199 m_iteratorLock.lockForRead();
200 td->m_swapLock.lockForWrite();
201
202 if (!td->data()) {
204 } else {
206 }
207
208 td->m_swapLock.unlock();
209 m_iteratorLock.unlock();
210
211 delete td;
212}
void forgetTileData(KisTileData *td)
void unregisterTileDataImp(KisTileData *td)
KisTileDataStore * m_store
#define DEBUG_FREE_ACTION(td)

References KisTileData::data(), DEBUG_FREE_ACTION, KisSwappedDataStore::forgetTileData(), m_iteratorLock, KisTileData::m_store, KisTileData::m_swapLock, m_swappedStore, and unregisterTileDataImp().

◆ instance()

KisTileDataStore * KisTileDataStore::instance ( )
static

Definition at line 82 of file kis_tile_data_store.cc.

83{
84 return s_instance;
85}

◆ kickPooler()

void KisTileDataStore::kickPooler ( )
inline

Definition at line 95 of file kis_tile_data_store.h.

96 {
97 m_pooler.kick();
98
99 //FIXME: maybe, rename a function?
100 m_swapper.kick();
101 }

◆ memoryMetric()

qint64 KisTileDataStore::memoryMetric ( ) const
inline
See also
m_memoryMetric

Definition at line 75 of file kis_tile_data_store.h.

76 {
77 return m_memoryMetric.loadAcquire();
78 }

◆ memoryStatistics()

KisTileDataStore::MemoryStatistics KisTileDataStore::memoryStatistics ( )

Definition at line 87 of file kis_tile_data_store.cc.

88{
89 QReadLocker lock(&m_iteratorLock);
90
91 MemoryStatistics stats;
92
93 const qint64 metricCoeff = qint64(KisTileData::WIDTH) * KisTileData::HEIGHT;
94
95 stats.realMemorySize = m_pooler.lastRealMemoryMetric() * metricCoeff;
96 stats.historicalMemorySize = m_pooler.lastHistoricalMemoryMetric() * metricCoeff;
97 stats.poolSize = m_pooler.lastPoolMemoryMetric() * metricCoeff;
98
99 stats.totalMemorySize = memoryMetric() * metricCoeff + stats.poolSize;
100
101 stats.swapSize = m_swappedStore.totalSwapMemoryUsed();
102
103 return stats;
104}
qint64 lastRealMemoryMetric() const
qint64 lastHistoricalMemoryMetric() const
qint64 lastPoolMemoryMetric() const
qint64 memoryMetric() const
static const qint32 HEIGHT
static const qint32 WIDTH

References KisTileData::HEIGHT, KisTileDataStore::MemoryStatistics::historicalMemorySize, KisTileDataPooler::lastHistoricalMemoryMetric(), KisTileDataPooler::lastPoolMemoryMetric(), KisTileDataPooler::lastRealMemoryMetric(), m_iteratorLock, m_pooler, m_swappedStore, memoryMetric(), KisTileDataStore::MemoryStatistics::poolSize, KisTileDataStore::MemoryStatistics::realMemorySize, KisTileDataStore::MemoryStatistics::swapSize, KisTileDataStore::MemoryStatistics::totalMemorySize, KisSwappedDataStore::totalSwapMemoryUsed(), and KisTileData::WIDTH.

◆ numTiles()

qint32 KisTileDataStore::numTiles ( ) const
inline

Returns total number of tiles present: in memory or in a swap file

Definition at line 54 of file kis_tile_data_store.h.

55 {
56 return m_numTiles.loadAcquire() + m_swappedStore.numTiles();
57 }

◆ numTilesInMemory()

qint32 KisTileDataStore::numTilesInMemory ( ) const
inline

Returns the number of tiles present in memory only

Definition at line 62 of file kis_tile_data_store.h.

63 {
64 return m_numTiles.loadAcquire();
65 }

◆ registerTileData()

void KisTileDataStore::registerTileData ( KisTileData * td)

Definition at line 132 of file kis_tile_data_store.cc.

133{
134 QReadLocker lock(&m_iteratorLock);
136}

References m_iteratorLock, and registerTileDataImp().

◆ registerTileDataImp()

void KisTileDataStore::registerTileDataImp ( KisTileData * td)
inlineprivate

Definition at line 115 of file kis_tile_data_store.cc.

116{
117 int index = m_counter.fetchAndAddOrdered(1);
118 td->m_tileNumber = index;
119
120 // make sure that access to the hash table is guarded by GC block
121 // (it avoids removal of the referenced cells caused by concurrent
122 // migrations)
124 m_tileDataMap.assign(index, td);
127
128 m_numTiles.ref();
129 m_memoryMetric += td->pixelSize();
130}
Value assign(Key key, Value desired)
quint32 pixelSize() const
void lockRawPointerAccess()
Definition qsbr.h:105
void unlockRawPointerAccess()
Definition qsbr.h:110
void update()
Definition qsbr.h:93

References ConcurrentMap< K, V, KT, VT >::assign(), ConcurrentMap< K, V, KT, VT >::getGC(), QSBR::lockRawPointerAccess(), m_counter, m_memoryMetric, m_numTiles, m_tileDataMap, KisTileData::m_tileNumber, KisTileData::pixelSize(), QSBR::unlockRawPointerAccess(), and QSBR::update().

◆ testingRereadConfig()

◆ testingResumePooler()

void KisTileDataStore::testingResumePooler ( )
private

Definition at line 378 of file kis_tile_data_store.cc.

379{
380 m_pooler.start();
381}

References m_pooler.

◆ testingSuspendPooler()

void KisTileDataStore::testingSuspendPooler ( )
private

Definition at line 373 of file kis_tile_data_store.cc.

374{
376}

References m_pooler, and KisTileDataPooler::terminatePooler().

◆ tryForceUpdateMemoryStatisticsWhileIdle()

void KisTileDataStore::tryForceUpdateMemoryStatisticsWhileIdle ( )

Definition at line 106 of file kis_tile_data_store.cc.

107{
108 // in case the pooler is disabled, we should force it
109 // to update the stats
110 if (!m_pooler.isRunning()) {
112 }
113}

References KisTileDataPooler::forceUpdateMemoryStats(), and m_pooler.

◆ trySwapTileData()

bool KisTileDataStore::trySwapTileData ( KisTileData * td)

Try swap out the tile data. It may fail in case the tile is being accessed at the same moment of time.

This function is called with m_listLock acquired

Definition at line 262 of file kis_tile_data_store.cc.

263{
268 bool result = false;
269 if (!td->m_swapLock.tryLockForWrite()) return result;
270
271 if (td->data()) {
274 result = true;
275 }
276 }
277 td->m_swapLock.unlock();
278
279 return result;
280}
bool trySwapOutTileData(KisTileData *td)

References KisTileData::data(), KisTileData::m_swapLock, m_swappedStore, KisSwappedDataStore::trySwapOutTileData(), and unregisterTileDataImp().

◆ unregisterTileData()

void KisTileDataStore::unregisterTileData ( KisTileData * td)

Definition at line 161 of file kis_tile_data_store.cc.

162{
163 QReadLocker lock(&m_iteratorLock);
165}

References m_iteratorLock, and unregisterTileDataImp().

◆ unregisterTileDataImp()

void KisTileDataStore::unregisterTileDataImp ( KisTileData * td)
inlineprivate

Definition at line 138 of file kis_tile_data_store.cc.

139{
140 // make sure that access to the hash table is guarded by GC block
141 // (it avoids removal of the referenced cells caused by concurrent
142 // migrations)
144
145 if (m_clockIndex == td->m_tileNumber) {
146 do {
147 m_clockIndex.ref();
148 } while (!m_tileDataMap.get(m_clockIndex.loadAcquire()) && m_clockIndex < m_counter);
149 }
150
151 int index = td->m_tileNumber;
152 td->m_tileNumber = -1;
153 m_tileDataMap.erase(index);
155 m_memoryMetric -= td->pixelSize();
156
159}
Value erase(Key key)
Value get(Key key)

References KisTileData::deref(), ConcurrentMap< K, V, KT, VT >::erase(), ConcurrentMap< K, V, KT, VT >::get(), ConcurrentMap< K, V, KT, VT >::getGC(), QSBR::lockRawPointerAccess(), m_clockIndex, m_counter, m_memoryMetric, m_numTiles, m_tileDataMap, KisTileData::m_tileNumber, KisTileData::pixelSize(), QSBR::unlockRawPointerAccess(), and QSBR::update().

Friends And Related Symbol Documentation

◆ DeadlockyThread

friend class DeadlockyThread
friend

Definition at line 142 of file kis_tile_data_store.h.

◆ KisLowMemoryBenchmark

friend class KisLowMemoryBenchmark
friend

Definition at line 151 of file kis_tile_data_store.h.

◆ KisLowMemoryTests

friend class KisLowMemoryTests
friend

Definition at line 143 of file kis_tile_data_store.h.

◆ KisTileDataPoolerTest

friend class KisTileDataPoolerTest
friend

Definition at line 158 of file kis_tile_data_store.h.

◆ KisTileDataStoreTest

friend class KisTileDataStoreTest
friend

Definition at line 157 of file kis_tile_data_store.h.

◆ KisTiledDataManagerTest

friend class KisTiledDataManagerTest
friend

Definition at line 147 of file kis_tile_data_store.h.

Member Data Documentation

◆ m_clockIndex

QAtomicInt KisTileDataStore::m_clockIndex
private

Definition at line 169 of file kis_tile_data_store.h.

◆ m_counter

QAtomicInt KisTileDataStore::m_counter
private

Definition at line 168 of file kis_tile_data_store.h.

◆ m_iteratorLock

QReadWriteLock KisTileDataStore::m_iteratorLock
private

Definition at line 171 of file kis_tile_data_store.h.

◆ m_memoryMetric

QAtomicInt KisTileDataStore::m_memoryMetric
private

Definition at line 167 of file kis_tile_data_store.h.

◆ m_numTiles

QAtomicInt KisTileDataStore::m_numTiles
private

This metric is used for computing the volume of memory occupied by tile data objects. metric = num_bytes / (KisTileData::WIDTH * KisTileData::HEIGHT)

Definition at line 166 of file kis_tile_data_store.h.

◆ m_pooler

KisTileDataPooler KisTileDataStore::m_pooler
private

Definition at line 154 of file kis_tile_data_store.h.

◆ m_swappedStore

KisSwappedDataStore KisTileDataStore::m_swappedStore
private

Definition at line 159 of file kis_tile_data_store.h.

◆ m_swapper

KisTileDataSwapper KisTileDataStore::m_swapper
private

Definition at line 155 of file kis_tile_data_store.h.

◆ m_tileDataMap

ConcurrentMap<int, KisTileData*> KisTileDataStore::m_tileDataMap
private

Definition at line 170 of file kis_tile_data_store.h.


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