Masterwork From Distant Lands
ActivePublic

Authored by dkazakov on Aug 9 2017, 1:54 PM.
diff --git a/libs/image/tiles3/kis_tile_hash_table.h b/libs/image/tiles3/kis_tile_hash_table.h
index 8224fc4..7249a52 100644
--- a/libs/image/tiles3/kis_tile_hash_table.h
+++ b/libs/image/tiles3/kis_tile_hash_table.h
@@ -21,7 +21,10 @@
#define KIS_TILEHASHTABLE_H_
#include "kis_tile.h"
+#include <array>
+#include <boost/thread/lock_guard.hpp>
+#include <boost/thread/shared_lock_guard.hpp>
/**
@@ -95,26 +98,66 @@ public:
void debugPrintInfo();
void debugMaxListLength(qint32 &min, qint32 &max);
+
+ void lock() {
+ for (int i = 0; i < LOCKS_SIZE; i++) {
+ m_tableLocks[i].lockForWrite();
+ }
+ }
+
+ void lock_shared() {
+ for (int i = 0; i < LOCKS_SIZE; i++) {
+ m_tableLocks[i].lockForRead();
+ }
+ }
+
+ void unlock() {
+ for (int i = LOCKS_SIZE - 1; i >= 0; i--) {
+ m_tableLocks[i].unlock();
+ }
+ }
+
+ void unlock_shared() {
+ for (int i = LOCKS_SIZE - 1; i >= 0; i--) {
+ m_tableLocks[i].unlock();
+ }
+ }
+
+ static inline quint32 calculateHash(qint32 col, qint32 row);
+
+
private:
- TileTypeSP getTile(qint32 col, qint32 row);
- void linkTile(TileTypeSP tile);
- TileTypeSP unlinkTile(qint32 col, qint32 row);
+ TileTypeSP getTile(qint32 col, qint32 row, qint32 idx);
+ void linkTile(TileTypeSP tile, qint32 idx);
+ TileTypeSP unlinkTile(qint32 col, qint32 row, qint32 idx);
inline void setDefaultTileDataImp(KisTileData *defaultTileData);
inline KisTileData* defaultTileDataImp() const;
- static inline quint32 calculateHash(qint32 col, qint32 row);
-
inline qint32 debugChainLen(qint32 idx);
void debugListLengthDistibution();
void sanityChecksumCheck();
private:
template<class U> friend class KisTileHashTableIteratorTraits;
+ typedef boost::shared_lock_guard<KisTileHashTableTraits<T>> ReadLockerImpl;
+ typedef boost::lock_guard<KisTileHashTableTraits<T>> WriteLockerImpl;
+
+ struct ReadLocker : public ReadLockerImpl {
+ ReadLocker(KisTileHashTableTraits<T> *obj) : ReadLockerImpl(*obj) {}
+ };
+
+ struct WriteLocker : public WriteLockerImpl {
+ WriteLocker(KisTileHashTableTraits<T> *obj) : WriteLockerImpl(*obj) {}
+ };
+
static const qint32 TABLE_SIZE = 1024;
+ static constexpr qint32 LOCKS_SIZE = 16;
+ static constexpr qint32 LOCKS_SHIFT = 6;
TileTypeSP *m_hashTable;
qint32 m_numTiles;
+ std::array<QReadWriteLock, LOCKS_SIZE> m_tableLocks;
KisTileData *m_defaultTileData;
KisMementoManager *m_mementoManager;
@@ -145,12 +188,15 @@ public:
if (m_index < KisTileHashTableTraits<T>::TABLE_SIZE)
m_tile = m_hashTable->m_hashTable[m_index];
- m_hashTable->m_lock.lockForWrite();
+ //m_hashTable->m_lock.lockForWrite();
+ m_hashTable->lock();
}
~KisTileHashTableIteratorTraits<T>() {
- if (m_index != -1)
- m_hashTable->m_lock.unlock();
+ if (m_index != -1) {
+ //m_hashTable->m_lock.unlock();
+ m_hashTable->unlock();
+ }
}
KisTileHashTableIteratorTraits<T>& operator++() {
@@ -184,20 +230,25 @@ public:
void deleteCurrent() {
TileTypeSP tile = m_tile;
next();
- m_hashTable->unlinkTile(tile->col(), tile->row());
+
+ const qint32 idx = m_hashTable->calculateHash(tile->col(), tile->row());
+ m_hashTable->unlinkTile(tile->col(), tile->row(), idx);
}
void moveCurrentToHashTable(KisTileHashTableTraits<T> *newHashTable) {
TileTypeSP tile = m_tile;
next();
- m_hashTable->unlinkTile(tile->col(), tile->row());
+
+ const qint32 idx = m_hashTable->calculateHash(tile->col(), tile->row());
+ m_hashTable->unlinkTile(tile->col(), tile->row(), idx);
newHashTable->addTile(tile);
}
void destroy() {
m_index = -1;
- m_hashTable->m_lock.unlock();
+ m_hashTable->unlock();
+ //m_hashTable->m_lock.unlock();
}
protected:
TileTypeSP m_tile;
diff --git a/libs/image/tiles3/kis_tile_hash_table_p.h b/libs/image/tiles3/kis_tile_hash_table_p.h
index abcad46..1968466 100644
--- a/libs/image/tiles3/kis_tile_hash_table_p.h
+++ b/libs/image/tiles3/kis_tile_hash_table_p.h
@@ -23,6 +23,8 @@
//#define SHARED_TILES_SANITY_CHECK
+#include <mutex>
+
template<class T>
KisTileHashTableTraits<T>::KisTileHashTableTraits(KisMementoManager *mm)
@@ -41,7 +43,7 @@ KisTileHashTableTraits<T>::KisTileHashTableTraits(const KisTileHashTableTraits<T
KisMementoManager *mm)
: m_lock(QReadWriteLock::NonRecursive)
{
- QReadLocker locker(&ht.m_lock);
+ ReadLocker locker(const_cast<KisTileHashTableTraits<T>*>(&ht));
m_mementoManager = mm;
m_defaultTileData = 0;
@@ -87,9 +89,8 @@ quint32 KisTileHashTableTraits<T>::calculateHash(qint32 col, qint32 row)
template<class T>
typename KisTileHashTableTraits<T>::TileTypeSP
-KisTileHashTableTraits<T>::getTile(qint32 col, qint32 row)
+KisTileHashTableTraits<T>::getTile(qint32 col, qint32 row, qint32 idx)
{
- qint32 idx = calculateHash(col, row);
TileTypeSP tile = m_hashTable[idx];
for (; tile; tile = tile->next()) {
@@ -104,9 +105,8 @@ KisTileHashTableTraits<T>::getTile(qint32 col, qint32 row)
}
template<class T>
-void KisTileHashTableTraits<T>::linkTile(TileTypeSP tile)
+void KisTileHashTableTraits<T>::linkTile(TileTypeSP tile, qint32 idx)
{
- qint32 idx = calculateHash(tile->col(), tile->row());
TileTypeSP firstTile = m_hashTable[idx];
#ifdef SHARED_TILES_SANITY_CHECK
@@ -121,9 +121,8 @@ void KisTileHashTableTraits<T>::linkTile(TileTypeSP tile)
template<class T>
typename KisTileHashTableTraits<T>::TileTypeSP
-KisTileHashTableTraits<T>::unlinkTile(qint32 col, qint32 row)
+KisTileHashTableTraits<T>::unlinkTile(qint32 col, qint32 row, qint32 idx)
{
- qint32 idx = calculateHash(col, row);
TileTypeSP tile = m_hashTable[idx];
TileTypeSP prevTile;
@@ -179,16 +178,22 @@ inline KisTileData* KisTileHashTableTraits<T>::defaultTileDataImp() const
template<class T>
bool KisTileHashTableTraits<T>::tileExists(qint32 col, qint32 row)
{
- QReadLocker locker(&m_lock);
- return getTile(col, row);
+ const qint32 idx = calculateHash(col, row);
+
+ //ReadLocker locker(this);
+ QReadLocker locker(&m_tableLocks[idx >> LOCKS_SHIFT]);
+ return getTile(col, row, idx);
}
template<class T>
typename KisTileHashTableTraits<T>::TileTypeSP
KisTileHashTableTraits<T>::getExistingTile(qint32 col, qint32 row)
{
- QReadLocker locker(&m_lock);
- return getTile(col, row);
+ const qint32 idx = calculateHash(col, row);
+
+ //ReadLocker locker(this);
+ QReadLocker locker(&m_tableLocks[idx >> LOCKS_SHIFT]);
+ return getTile(col, row, idx);
}
template<class T>
@@ -196,16 +201,25 @@ typename KisTileHashTableTraits<T>::TileTypeSP
KisTileHashTableTraits<T>::getTileLazy(qint32 col, qint32 row,
bool& newTile)
{
+ const qint32 idx = calculateHash(col, row);
+
newTile = false;
- TileTypeSP tile = getExistingTile(col, row);
+ TileTypeSP tile;
+
+ {
+ //ReadLocker locker(this);
+ QReadLocker locker(&m_tableLocks[idx >> LOCKS_SHIFT]);
+ tile = getTile(col, row, idx);
+ }
if (!tile) {
- QWriteLocker locker(&m_lock);
- tile = getTile(col, row);
+ //WriteLocker locker(this);
+ QWriteLocker locker(&m_tableLocks[idx >> LOCKS_SHIFT]);
+ tile = getTile(col, row, idx);
if (!tile) {
tile = new TileType(col, row, m_defaultTileData, m_mementoManager);
- linkTile(tile);
+ linkTile(tile, idx);
newTile = true;
}
}
@@ -217,9 +231,11 @@ template<class T>
typename KisTileHashTableTraits<T>::TileTypeSP
KisTileHashTableTraits<T>::getReadOnlyTileLazy(qint32 col, qint32 row)
{
- QReadLocker locker(&m_lock);
+ const qint32 idx = calculateHash(col, row);
+ //ReadLocker locker(this);
+ QReadLocker locker(&m_tableLocks[idx >> LOCKS_SHIFT]);
- TileTypeSP tile = getTile(col, row);
+ TileTypeSP tile = getTile(col, row, idx);
if (!tile)
tile = new TileType(col, row, m_defaultTileData, 0);
@@ -229,16 +245,22 @@ KisTileHashTableTraits<T>::getReadOnlyTileLazy(qint32 col, qint32 row)
template<class T>
void KisTileHashTableTraits<T>::addTile(TileTypeSP tile)
{
- QWriteLocker locker(&m_lock);
- linkTile(tile);
+ const qint32 idx = calculateHash(tile->col(), tile->row());
+
+ //WriteLocker locker(this);
+ QWriteLocker locker(&m_tableLocks[idx >> LOCKS_SHIFT]);
+ linkTile(tile, idx);
}
template<class T>
void KisTileHashTableTraits<T>::deleteTile(qint32 col, qint32 row)
{
- QWriteLocker locker(&m_lock);
+ const qint32 idx = calculateHash(col, row);
+
+ //WriteLocker locker(this);
+ QWriteLocker locker(&m_tableLocks[idx >> LOCKS_SHIFT]);
- TileTypeSP tile = unlinkTile(col, row);
+ TileTypeSP tile = unlinkTile(col, row, idx);
/* Done by KisSharedPtr */
//if(tile)
@@ -255,7 +277,7 @@ void KisTileHashTableTraits<T>::deleteTile(TileTypeSP tile)
template<class T>
void KisTileHashTableTraits<T>::clear()
{
- QWriteLocker locker(&m_lock);
+ WriteLocker locker(this);
TileTypeSP tile = TileTypeSP();
qint32 i;
@@ -286,14 +308,14 @@ void KisTileHashTableTraits<T>::clear()
template<class T>
void KisTileHashTableTraits<T>::setDefaultTileData(KisTileData *defaultTileData)
{
- QWriteLocker locker(&m_lock);
+ WriteLocker locker(this);
setDefaultTileDataImp(defaultTileData);
}
template<class T>
KisTileData* KisTileHashTableTraits<T>::defaultTileData() const
{
- QWriteLocker locker(&m_lock);
+ WriteLocker locker(const_cast<KisTileHashTableTraits<T>*>(this));
return defaultTileDataImp();
}
dkazakov edited the content of this paste. (Show Details)Aug 9 2017, 1:54 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.