Krita Source Code Documentation
Loading...
Searching...
No Matches
KisTiledExtentManager::Data Class Reference

Public Member Functions

bool add (qint32 index)
 
void clear ()
 
 Data ()
 
bool isEmpty ()
 
qint32 max ()
 
qint32 min ()
 
bool remove (qint32 index)
 
void replace (const QVector< qint32 > &indexes)
 
 ~Data ()
 

Public Attributes

QReadWriteLock m_extentLock
 

Private Member Functions

void migrate (qint32 index)
 
void unsafeAdd (qint32 index)
 
void unsafeMigrate (qint32 index)
 
void updateMax ()
 
void updateMin ()
 

Private Attributes

QAtomicInt * m_buffer
 
qint32 m_capacity
 
qint32 m_count
 
qint32 m_max
 
QReadWriteLock m_migrationLock
 
qint32 m_min
 
qint32 m_offset
 

Detailed Description

Definition at line 21 of file KisTiledExtentManager.h.

Constructor & Destructor Documentation

◆ Data()

◆ ~Data()

KisTiledExtentManager::Data::~Data ( )

Definition at line 25 of file KisTiledExtentManager.cpp.

26{
27 QWriteLocker lock(&m_migrationLock);
28 delete[] m_buffer;
29}

Member Function Documentation

◆ add()

bool KisTiledExtentManager::Data::add ( qint32 index)

Definition at line 31 of file KisTiledExtentManager.cpp.

32{
33 QReadLocker lock(&m_migrationLock);
34 qint32 currentIndex = m_offset + index;
35
36 if (currentIndex < 0 || currentIndex >= m_capacity) {
37 lock.unlock();
38 migrate(index);
39 lock.relock();
40 currentIndex = m_offset + index;
41 }
42
43 KIS_ASSERT_RECOVER_NOOP(m_buffer[currentIndex].loadAcquire() >= 0);
44 bool needsUpdateExtent = false;
45
46 while (true) {
47 QReadLocker rl(&m_extentLock);
48
49 int oldValue = m_buffer[currentIndex].loadAcquire();
50 if (oldValue == 0) {
51 rl.unlock();
52 QWriteLocker wl(&m_extentLock);
53
54 if ((oldValue = m_buffer[currentIndex].loadAcquire()) == 0) {
55
56 if (m_min > index) m_min = index;
57 if (m_max < index) m_max = index;
58
59 ++m_count;
60 needsUpdateExtent = true;
61
62 m_buffer[currentIndex].storeRelease(1);
63 } else {
64 m_buffer[currentIndex].storeRelease(oldValue + 1);
65 }
66
67 break;
68 } else if (m_buffer[currentIndex].testAndSetOrdered(oldValue, oldValue + 1)) {
69 break;
70 }
71 }
72
73 return needsUpdateExtent;
74}
#define KIS_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:97

References KIS_ASSERT_RECOVER_NOOP, and KisTiledExtentManager::m_extentLock.

◆ clear()

void KisTiledExtentManager::Data::clear ( )

Definition at line 130 of file KisTiledExtentManager.cpp.

131{
132 QWriteLocker lock(&m_migrationLock);
133 QWriteLocker l(&m_extentLock);
134
135 for (qint32 i = 0; i < m_capacity; ++i) {
136 m_buffer[i].storeRelaxed(0);
137 }
138
141 m_count = 0;
142}

References KisTiledExtentManager::m_extentLock, qint32_MAX, and qint32_MIN.

◆ isEmpty()

bool KisTiledExtentManager::Data::isEmpty ( )

Definition at line 144 of file KisTiledExtentManager.cpp.

145{
146 return m_count == 0;
147}

◆ max()

qint32 KisTiledExtentManager::Data::max ( )

Definition at line 154 of file KisTiledExtentManager.cpp.

155{
156 return m_max;
157}

◆ migrate()

void KisTiledExtentManager::Data::migrate ( qint32 index)
inlineprivate

Definition at line 203 of file KisTiledExtentManager.cpp.

204{
205 QWriteLocker lock(&m_migrationLock);
206 unsafeMigrate(index);
207}

◆ min()

qint32 KisTiledExtentManager::Data::min ( )

Definition at line 149 of file KisTiledExtentManager.cpp.

150{
151 return m_min;
152}

◆ remove()

bool KisTiledExtentManager::Data::remove ( qint32 index)

That is not the droid you're looking for. If you see this assert in the backtrace, most probably, the bug is not here. The crash happens because two threads are trying to do device->clear(rc) concurrently for the overlapping rects. That is, they are trying to remove the same tile. Look higher!

Definition at line 76 of file KisTiledExtentManager.cpp.

77{
78 QReadLocker lock(&m_migrationLock);
79 qint32 currentIndex = m_offset + index;
80
81 bool needsUpdateExtent = false;
82 QReadLocker rl(&m_extentLock);
83
84 const int oldValue = m_buffer[currentIndex].fetchAndAddAcquire(-1);
85
93 KIS_SAFE_ASSERT_RECOVER(oldValue > 0) {
94 m_buffer[currentIndex].storeRelaxed(0);
95 return false;
96 }
97
98 if (oldValue == 1) {
99 rl.unlock();
100 QWriteLocker wl(&m_extentLock);
101
102 if (m_min == index) updateMin();
103 if (m_max == index) updateMax();
104
105 --m_count;
106 needsUpdateExtent = true;
107 }
108
109 return needsUpdateExtent;
110}
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126

References KIS_SAFE_ASSERT_RECOVER, and KisTiledExtentManager::m_extentLock.

◆ replace()

void KisTiledExtentManager::Data::replace ( const QVector< qint32 > & indexes)

Definition at line 112 of file KisTiledExtentManager.cpp.

113{
114 QWriteLocker lock(&m_migrationLock);
115 QWriteLocker l(&m_extentLock);
116
117 for (qint32 i = 0; i < m_capacity; ++i) {
118 m_buffer[i].storeRelaxed(0);
119 }
120
123 m_count = 0;
124
125 Q_FOREACH (const qint32 index, indexes) {
126 unsafeAdd(index);
127 }
128}

References KisTiledExtentManager::m_extentLock, qint32_MAX, and qint32_MIN.

◆ unsafeAdd()

void KisTiledExtentManager::Data::unsafeAdd ( qint32 index)
inlineprivate

Definition at line 159 of file KisTiledExtentManager.cpp.

160{
161 qint32 currentIndex = m_offset + index;
162
163 if (currentIndex < 0 || currentIndex >= m_capacity) {
164 unsafeMigrate(index);
165 currentIndex = m_offset + index;
166 }
167
168 if (!m_buffer[currentIndex].fetchAndAddRelaxed(1)) {
169 if (m_min > index) m_min = index;
170 if (m_max < index) m_max = index;
171 ++m_count;
172 }
173}

◆ unsafeMigrate()

void KisTiledExtentManager::Data::unsafeMigrate ( qint32 index)
inlineprivate

Definition at line 175 of file KisTiledExtentManager.cpp.

176{
177 qint32 oldCapacity = m_capacity;
178 qint32 oldOffset = m_offset;
179 qint32 currentIndex = m_offset + index;
180
181 while (currentIndex < 0 || currentIndex >= m_capacity) {
182 m_capacity <<= 1;
183
184 if (currentIndex < 0) {
185 m_offset <<= 1;
186 currentIndex = m_offset + index;
187 }
188 }
189
190 if (m_capacity != oldCapacity) {
191 QAtomicInt *newBuffer = new QAtomicInt[m_capacity];
192 qint32 start = m_offset - oldOffset;
193
194 for (qint32 i = 0; i < oldCapacity; ++i) {
195 newBuffer[start + i].storeRelaxed(m_buffer[i].loadRelaxed());
196 }
197
198 delete[] m_buffer;
199 m_buffer = newBuffer;
200 }
201}

◆ updateMax()

void KisTiledExtentManager::Data::updateMax ( )
inlineprivate

Definition at line 227 of file KisTiledExtentManager.cpp.

228{
230
231 qint32 start = m_max + m_offset;
232
233 for (qint32 i = start; i >= 0; --i) {
234 qint32 current = m_buffer[i].loadRelaxed();
235
236 if (current > 0) {
237 m_max = i - m_offset;
238 return;
239 }
240 }
241
243}
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130

References KIS_SAFE_ASSERT_RECOVER_NOOP, and qint32_MIN.

◆ updateMin()

void KisTiledExtentManager::Data::updateMin ( )
inlineprivate

Definition at line 209 of file KisTiledExtentManager.cpp.

210{
212
213 qint32 start = m_min + m_offset;
214
215 for (qint32 i = start; i < m_capacity; ++i) {
216 qint32 current = m_buffer[i].loadRelaxed();
217
218 if (current > 0) {
219 m_min = i - m_offset;
220 return;
221 }
222 }
223
225}

References KIS_SAFE_ASSERT_RECOVER_NOOP, and qint32_MAX.

Member Data Documentation

◆ m_buffer

QAtomicInt* KisTiledExtentManager::Data::m_buffer
private

Definition at line 51 of file KisTiledExtentManager.h.

◆ m_capacity

qint32 KisTiledExtentManager::Data::m_capacity
private

Definition at line 49 of file KisTiledExtentManager.h.

◆ m_count

qint32 KisTiledExtentManager::Data::m_count
private

Definition at line 50 of file KisTiledExtentManager.h.

◆ m_extentLock

QReadWriteLock KisTiledExtentManager::Data::m_extentLock

Definition at line 36 of file KisTiledExtentManager.h.

◆ m_max

qint32 KisTiledExtentManager::Data::m_max
private

Definition at line 47 of file KisTiledExtentManager.h.

◆ m_migrationLock

QReadWriteLock KisTiledExtentManager::Data::m_migrationLock
private

Definition at line 52 of file KisTiledExtentManager.h.

◆ m_min

qint32 KisTiledExtentManager::Data::m_min
private

Definition at line 46 of file KisTiledExtentManager.h.

◆ m_offset

qint32 KisTiledExtentManager::Data::m_offset
private

Definition at line 48 of file KisTiledExtentManager.h.


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