Masterwork From Distant Lands
ActivePublic

Authored by dkazakov on Aug 4 2017, 1:10 PM.
diff --git a/libs/image/tiles3/KisOptimizedTileDataList.h b/libs/image/tiles3/KisOptimizedTileDataList.h
index ea280a5..9264d56 100644
--- a/libs/image/tiles3/KisOptimizedTileDataList.h
+++ b/libs/image/tiles3/KisOptimizedTileDataList.h
@@ -19,11 +19,95 @@
#ifndef KISOPTIMIZEDTILEDATALIST_H
#define KISOPTIMIZEDTILEDATALIST_H
+#include <QMutex>
+#include <QLinkedList>
+#include <QAtomicInteger>
+#include "kis_lockless_stack.h"
+#include "kis_tile_data_interface.h"
-class KisOptimizedTileDataList
+class KisOptimizedTileDataList;
+typedef KisOptimizedTileDataList::iterator KisOptimizedTileDataListIterator;
+typedef KisOptimizedTileDataList::const_iterator KisOptimizedTileDataListConstIterator;
+
+
+class KisOptimizedTileDataList : public QLinkedList<KisTileData*>
{
public:
- KisOptimizedTileDataList();
+ //KisOptimizedTileDataList();
+
+
+ void registerTileData(KisTileData *td) {
+ m_numTiles.ref();
+ m_numTiles.fetchAndAddOrdered(td->pixelSize());
+ }
+
+ inline int numTiles() const {
+ return m_numTiles;
+ }
+
+ inline int memoryMetric() const {
+ return m_memoryMetric;
+ }
+
+ void lock() {
+ m_mutex.lock();
+ m_lockCount.ref();
+
+ KisTileData *td = 0;
+ while (m_pendingTiles.pop(td)) {
+ registerTileDataImp(td);
+ }
+
+ while (m_discardedTiles.pop(td)) {
+ unregisterTileDataImp(td);
+ }
+ }
+
+ void unlock() {
+ m_mutex.unlock();
+ }
+
+ KisOptimizedTileDataListIterator clockIterator() const {
+ return m_clockIterator;
+ }
+
+ void setClockIterator(KisOptimizedTileDataListIterator value) {
+ m_clockIterator = value;
+ }
+
+private:
+ inline void registerTileDataImp(KisTileData *td) {
+ td->m_listIterator = this->insert(this->end(), td);
+ }
+
+ inline void unregisterTileDataImp(KisTileData *td) {
+ KisOptimizedTileDataListIterator tempIterator = td->m_listIterator;
+
+ if(m_clockIterator == tempIterator) {
+ m_clockIterator = tempIterator + 1;
+ }
+
+ td->m_listIterator = this->end();
+ this->erase(tempIterator);
+ }
+
+
+
+private:
+ QMutex m_mutex;
+
+ QAtomicInteger m_numTiles;
+ QAtomicInteger m_memoryMetric;
+
+ QAtomicInteger m_lockCount;
+
+ KisOptimizedTileDataListIterator m_clockIterator;
+
+ KisLocklessStack<KisTileData*> m_pendingTiles;
+ KisLocklessStack<KisTileData*> m_discardedTiles;
};
+typedef KisOptimizedTileDataList::iterator KisOptimizedTileDataListIterator;
+typedef KisOptimizedTileDataList::const_iterator KisOptimizedTileDataListConstIterator;
+
#endif // KISOPTIMIZEDTILEDATALIST_H
diff --git a/libs/image/tiles3/kis_tile_data.h b/libs/image/tiles3/kis_tile_data.h
index dee8a37..03f881b 100644
--- a/libs/image/tiles3/kis_tile_data.h
+++ b/libs/image/tiles3/kis_tile_data.h
@@ -78,14 +78,14 @@ inline bool KisTileData::deref() {
bool _ref;
if (!(_ref = m_refCount.deref())) {
- m_store->freeTileData(this);
+ m_store->freeTileDataOptimized(this);
return 0;
}
return _ref;
}
inline KisTileData* KisTileData::clone() {
- return m_store->duplicateTileData(this);
+ return m_store->duplicateTileDataOptimized(this);
}
inline void KisTileData::blockSwapping() {
diff --git a/libs/image/tiles3/kis_tile_data_store.cc b/libs/image/tiles3/kis_tile_data_store.cc
index 38978fb..d2546ba 100644
--- a/libs/image/tiles3/kis_tile_data_store.cc
+++ b/libs/image/tiles3/kis_tile_data_store.cc
@@ -96,7 +96,9 @@ KisTileDataStore* KisTileDataStore::instance()
KisTileDataStore::MemoryStatistics KisTileDataStore::memoryStatistics()
{
- QMutexLocker lock(&m_listLock);
+ //QMutexLocker lock(&m_listLock);
+
+ lockList();
MemoryStatistics stats;
@@ -110,6 +112,8 @@ KisTileDataStore::MemoryStatistics KisTileDataStore::memoryStatistics()
stats.swapSize = m_swappedStore.totalMemoryMetric() * metricCoeff;
+ unlockList();
+
return stats;
}
@@ -140,16 +144,17 @@ inline void KisTileDataStore::unregisterTileDataImp(KisTileData *td)
m_memoryMetric -= td->pixelSize();
}
-void KisTileDataStore::unregisterTileData(KisTileData *td)
+KisTileData *KisTileDataStore::createDefaultTileData(qint32 pixelSize, const quint8 *defPixel)
{
- QMutexLocker lock(&m_listLock);
- unregisterTileDataImp(td);
+ KisTileData *td = new KisTileData(pixelSize, defPixel, this);
+ registerTileData(td);
+ return td;
}
-KisTileData *KisTileDataStore::allocTileData(qint32 pixelSize, const quint8 *defPixel)
+KisTileData *KisTileDataStore::createDefaultTileDataOptimized(qint32 pixelSize, const quint8 *defPixel)
{
KisTileData *td = new KisTileData(pixelSize, defPixel, this);
- registerTileData(td);
+ m_pendingTiles.push(td);
return td;
}
@@ -172,6 +177,25 @@ KisTileData *KisTileDataStore::duplicateTileData(KisTileData *rhs)
return td;
}
+KisTileData *KisTileDataStore::duplicateTileDataOptimized(KisTileData *rhs)
+{
+ KisTileData *td = 0;
+
+ if (rhs->m_clonesStack.pop(td)) {
+ DEBUG_PRECLONE_ACTION("+ Pre-clone HIT", rhs, td);
+ DEBUG_COUNT_PRECLONE_HIT(rhs);
+ } else {
+ rhs->blockSwapping();
+ td = new KisTileData(*rhs);
+ rhs->unblockSwapping();
+ DEBUG_PRECLONE_ACTION("- Pre-clone #MISS#", rhs, td);
+ DEBUG_COUNT_PRECLONE_MISS(rhs);
+ }
+
+ m_pendingTiles.push(td);
+ return td;
+}
+
void KisTileDataStore::freeTileData(KisTileData *td)
{
Q_ASSERT(td->m_store == this);
@@ -194,6 +218,11 @@ void KisTileDataStore::freeTileData(KisTileData *td)
delete td;
}
+void KisTileDataStore::freeTileDataOptimized(KisTileData *td)
+{
+ m_discardedTiles.push(td);
+}
+
void KisTileDataStore::ensureTileDataLoaded(KisTileData *td)
{
// dbgKrita << "#### SWAP MISS! ####" << td << ppVar(td->mementoed()) << ppVar(td->age()) << ppVar(td->numUsers());
@@ -263,37 +292,43 @@ bool KisTileDataStore::trySwapTileData(KisTileData *td)
KisTileDataStoreIterator* KisTileDataStore::beginIteration()
{
- m_listLock.lock();
+ //m_listLock.lock();
+ lockList();
return new KisTileDataStoreIterator(m_tileDataList, this);
}
void KisTileDataStore::endIteration(KisTileDataStoreIterator* iterator)
{
delete iterator;
- m_listLock.unlock();
+ unlockList();
+ //m_listLock.unlock();
}
KisTileDataStoreReverseIterator* KisTileDataStore::beginReverseIteration()
{
- m_listLock.lock();
+ //m_listLock.lock();
+ lockList();
return new KisTileDataStoreReverseIterator(m_tileDataList, this);
}
void KisTileDataStore::endIteration(KisTileDataStoreReverseIterator* iterator)
{
delete iterator;
- m_listLock.unlock();
+ //m_listLock.unlock();
+ unlockList();
DEBUG_REPORT_PRECLONE_EFFICIENCY();
}
KisTileDataStoreClockIterator* KisTileDataStore::beginClockIteration()
{
- m_listLock.lock();
+ //m_listLock.lock();
+ lockList();
return new KisTileDataStoreClockIterator(m_clockIterator, m_tileDataList, this);
}
void KisTileDataStore::endIteration(KisTileDataStoreClockIterator* iterator)
{
m_clockIterator = iterator->getFinalPosition();
delete iterator;
- m_listLock.unlock();
+ //m_listLock.unlock();
+ unlockList();
}
void KisTileDataStore::debugPrintList()
@@ -323,7 +358,8 @@ void KisTileDataStore::debugSwapAll()
void KisTileDataStore::debugClear()
{
- QMutexLocker lock(&m_listLock);
+ //QMutexLocker lock(&m_listLock);
+ lockList();
Q_FOREACH (KisTileData *item, m_tileDataList) {
delete item;
@@ -334,6 +370,8 @@ void KisTileDataStore::debugClear()
m_numTiles = 0;
m_memoryMetric = 0;
+
+ unlockList();
}
void KisTileDataStore::testingRereadConfig() {
@@ -342,6 +380,25 @@ void KisTileDataStore::testingRereadConfig() {
kickPooler();
}
+void KisTileDataStore::lockList()
+{
+ KisTileData *td = 0;
+ while (m_pendingTiles.pop(td)) {
+ registerTileData(td);
+ }
+
+ while (m_discardedTiles.pop(td)) {
+ freeTileData(td);
+ }
+
+ m_listLock.lock();
+}
+
+void KisTileDataStore::unlockList()
+{
+ m_listLock.unlock();
+}
+
void KisTileDataStore::testingSuspendPooler()
{
m_pooler.terminatePooler();
diff --git a/libs/image/tiles3/kis_tile_data_store.h b/libs/image/tiles3/kis_tile_data_store.h
index 4477c3b..9582935 100644
--- a/libs/image/tiles3/kis_tile_data_store.h
+++ b/libs/image/tiles3/kis_tile_data_store.h
@@ -90,9 +90,8 @@ public:
KisTileDataStoreClockIterator* beginClockIteration();
void endIteration(KisTileDataStoreClockIterator* iterator);
- inline KisTileData* createDefaultTileData(qint32 pixelSize, const quint8 *defPixel) {
- return allocTileData(pixelSize, defPixel);
- }
+ KisTileData* createDefaultTileData(qint32 pixelSize, const quint8 *defPixel);
+ KisTileData* createDefaultTileDataOptimized(qint32 pixelSize, const quint8 *defPixel);
// Called by The Memento Manager after every commit
inline void kickPooler() {
@@ -116,8 +115,10 @@ public:
*/
KisTileData *duplicateTileData(KisTileData *rhs);
+ KisTileData *duplicateTileDataOptimized(KisTileData *rhs);
void freeTileData(KisTileData *td);
+ void freeTileDataOptimized(KisTileData *td);
/**
* Ensures that the tile data is totally present in memory
@@ -132,10 +133,7 @@ public:
void ensureTileDataLoaded(KisTileData *td);
private:
- KisTileData *allocTileData(qint32 pixelSize, const quint8 *defPixel);
-
void registerTileData(KisTileData *td);
- void unregisterTileData(KisTileData *td);
inline void registerTileDataImp(KisTileData *td);
inline void unregisterTileDataImp(KisTileData *td);
void freeRegisteredTiles();
@@ -151,6 +149,10 @@ private:
friend class KisLowMemoryBenchmark;
void testingRereadConfig();
+
+ void lockList();
+ void unlockList();
+
private:
KisTileDataPooler m_pooler;
KisTileDataSwapper m_swapper;
@@ -163,14 +165,17 @@ private:
QMutex m_listLock;
KisTileDataList m_tileDataList;
- qint32 m_numTiles;
+ QAtomicInteger<qint32> m_numTiles;
/**
* This metric is used for computing the volume
* of memory occupied by tile data objects.
* metric = num_bytes / (KisTileData::WIDTH * KisTileData::HEIGHT)
*/
- qint64 m_memoryMetric;
+ QAtomicInteger<qint64> m_memoryMetric;
+
+ KisLocklessStack<KisTileData*> m_pendingTiles;
+ KisLocklessStack<KisTileData*> m_discardedTiles;
};
template<typename T>
diff --git a/libs/image/tiles3/kis_tiled_data_manager.cc b/libs/image/tiles3/kis_tiled_data_manager.cc
index 2191de5..0e3d3c3 100644
--- a/libs/image/tiles3/kis_tiled_data_manager.cc
+++ b/libs/image/tiles3/kis_tiled_data_manager.cc
@@ -107,7 +107,7 @@ void KisTiledDataManager::setDefaultPixel(const quint8 *defaultPixel)
void KisTiledDataManager::setDefaultPixelImpl(const quint8 *defaultPixel)
{
- KisTileData *td = KisTileDataStore::instance()->createDefaultTileData(pixelSize(), defaultPixel);
+ KisTileData *td = KisTileDataStore::instance()->createDefaultTileDataOptimized(pixelSize(), defaultPixel);
m_hashTable->setDefaultTileData(td);
m_mementoManager->setDefaultTileData(td);
@@ -369,7 +369,7 @@ void KisTiledDataManager::clear(QRect clearRect, const quint8 *clearPixel)
clearRect.width() >= KisTileData::WIDTH &&
clearRect.height() >= KisTileData::HEIGHT) {
- td = KisTileDataStore::instance()->createDefaultTileData(pixelSize, clearPixel);
+ td = KisTileDataStore::instance()->createDefaultTileDataOptimized(pixelSize, clearPixel);
td->acquire();
}
dkazakov edited the content of this paste. (Show Details)Aug 4 2017, 1:10 PM
dkazakov changed the title of this paste from untitled to Masterwork From Distant Lands.
dkazakov updated the paste's language from autodetect to autodetect.