Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_tile.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org>
3 * (c) 2009 Dmitry Kazakov <dimula73@gmail.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8
9#include <QMutexLocker>
10#include "kis_tile_data.h"
11#include "kis_tile_data_store.h"
12#include "kis_tile.h"
13#include "kis_memento_manager.h"
14#include "kis_debug.h"
15
16
17void KisTile::init(qint32 col, qint32 row,
18 KisTileData *defaultTileData, KisMementoManager* mm)
19{
20 m_col = col;
21 m_row = row;
22 m_lockCounter = 0;
23
26
27 m_tileData = defaultTileData;
29
30 if (mm) {
31 mm->registerTileChange(this);
32 }
33 m_mementoManager.storeRelease(mm);
34}
35
36KisTile::KisTile(qint32 col, qint32 row,
37 KisTileData *defaultTileData, KisMementoManager* mm)
38{
39 init(col, row, defaultTileData, mm);
40}
41
42KisTile::KisTile(const KisTile& rhs, qint32 col, qint32 row, KisMementoManager* mm)
43 : KisShared()
44{
45 init(col, row, rhs.tileData(), mm);
46}
47
49 : KisShared()
50{
51 init(rhs.col(), rhs.row(), rhs.tileData(), mm);
52}
53
55 : KisShared()
56{
57 init(rhs.col(), rhs.row(), rhs.tileData(), rhs.m_mementoManager);
58}
59
61{
62#ifdef DEAD_TILES_SANITY_CHECK
64
71 if (m_mementoManager) {
72 qDebug() << this << ppVar(m_sanityNumCOWHappened);
73 qDebug() << this << ppVar(m_sanityHasBeenDetached);
74 qDebug() << this << ppVar(m_sanityMMHasBeenInitializedManually);
75 qDebug() << this << ppVar(m_sanityIsDead);
76 KIS_ASSERT(0 && "m_mementoManager is still initialized during destruction");
77 }
78#endif
79
81}
82
84{
85#ifdef DEAD_TILES_SANITY_CHECK
86 sanityCheckIsNotLockedForWrite();
87#endif
88
89 if (m_mementoManager.loadAcquire()) {
91 m_mementoManager.storeRelease(0);
92 manager->registerTileDeleted(this);
93 }
94
95#ifdef DEAD_TILES_SANITY_CHECK
96 m_sanityHasBeenDetached.ref();
97#endif
98}
99
101{
102#ifdef DEAD_TILES_SANITY_CHECK
103 sanityCheckIsNotLockedForWrite();
104#endif
105
106 m_mementoManager.storeRelease(0);
107
108#ifdef DEAD_TILES_SANITY_CHECK
109 m_sanityIsDead.ref();
110#endif
111}
112
114{
115#ifdef DEAD_TILES_SANITY_CHECK
116 sanityCheckIsNotDestroyedYet();
117#endif
118
119 // TODO: check if we really need locking here
120 if (!m_mementoManager.loadAcquire()) {
121 QMutexLocker locker(&m_COWMutex);
122
123 if (!m_mementoManager.loadAcquire()) {
124
125 if (mm) {
126 mm->registerTileChange(this);
127 }
128 m_mementoManager.storeRelease(mm);
129
130#ifdef DEAD_TILES_SANITY_CHECK
131 m_sanityMMHasBeenInitializedManually.ref();
132#endif
133 }
134 }
135
136#ifdef DEAD_TILES_SANITY_CHECK
137 sanityCheckIsNotDestroyedYet();
138#endif
139}
140
141//#define DEBUG_TILE_LOCKING
142//#define DEBUG_TILE_COWING
143
144#ifdef DEBUG_TILE_LOCKING
145#define DEBUG_LOG_ACTION(action) \
146 printf("### %s \ttile:\t0x%llX (%d, %d) (0x%llX) ###\n", action, (quintptr)this, m_col, m_row, (quintptr)m_tileData)
147#else
148#define DEBUG_LOG_ACTION(action)
149#endif
150
151#ifdef DEBUG_TILE_COWING
152#define DEBUG_COWING(newTD) \
153 printf("### COW done \ttile:\t0x%X (%d, %d) (0x%X -> 0x%X) [mm: 0x%X] ###\n", (quintptr)this, m_col, m_row, (quintptr)m_tileData, (quintptr)newTD, m_mementoManager);
154#else
155#define DEBUG_COWING(newTD)
156#endif
157
158inline void KisTile::blockSwapping() const
159{
167 QMutexLocker locker(&m_swapBarrierLock);
168 Q_ASSERT(m_lockCounter >= 0);
169
170 if(!m_lockCounter++)
172
173 Q_ASSERT(data());
174}
175
176inline void KisTile::unblockSwapping() const
177{
178 QMutexLocker locker(&m_swapBarrierLock);
179 Q_ASSERT(m_lockCounter > 0);
180
181 if(--m_lockCounter == 0) {
183
184 if(!m_oldTileData.isEmpty()) {
185 Q_FOREACH (KisTileData *td, m_oldTileData) {
186 td->unblockSwapping();
187 td->release();
188 }
189 m_oldTileData.clear();
190 }
191 }
192}
193
195{
196 QMutexLocker locker(&m_swapBarrierLock);
197 Q_ASSERT(m_lockCounter >= 0);
198
199 if(m_lockCounter > 0) {
200 m_oldTileData.push(td);
201 }
202 else {
203 td->unblockSwapping();
204 td->release();
205 }
206}
207
209{
210#ifdef DEAD_TILES_SANITY_CHECK
211 m_sanityLockedForRead.ref();
212#endif
213
214 DEBUG_LOG_ACTION("lock [R]");
216}
217
218
219#define lazyCopying() (m_tileData->m_usersCount>1)
220
222{
223#ifdef DEAD_TILES_SANITY_CHECK
224 m_sanityLockedForWrite.ref();
225#endif
226
228
229 /* We are doing COW here */
230 if (lazyCopying()) {
231 m_COWMutex.lock();
232
238 if (lazyCopying()) {
239
241 tileData->acquire();
243 KisTileData *oldTileData = m_tileData;
245 safeReleaseOldTileData(oldTileData);
246
248
249 KisMementoManager *mm = m_mementoManager.loadRelaxed();
250 if (mm) {
251 mm->registerTileChange(this);
252 }
253 }
254 m_COWMutex.unlock();
255
256#ifdef DEAD_TILES_SANITY_CHECK
257 m_sanityNumCOWHappened.ref();
258#endif
259 }
260
261 DEBUG_LOG_ACTION("lock [W]");
262}
263
265{
267 DEBUG_LOG_ACTION("unlock [W]");
268
269#ifdef DEAD_TILES_SANITY_CHECK
270 m_sanityLockedForWrite.deref();
271 KIS_ASSERT(m_sanityLockedForWrite.loadAcquire() >= 0);
272#endif
273}
274
276{
278 DEBUG_LOG_ACTION("unlock [R]");
279
280#ifdef DEAD_TILES_SANITY_CHECK
281 m_sanityLockedForRead.deref();
282 KIS_ASSERT(m_sanityLockedForRead.loadAcquire() >= 0);
283#endif
284}
285
286
287#include <stdio.h>
289{
290 dbgTiles << "------\n"
291 "Tile:\t\t\t" << this
292 << "\n data:\t" << m_tileData
293 << "\n next:\t" << m_nextTile.data();
294
295}
296
298{
299 lockForRead();
300 quint8 *data = this->data();
301
302 for (int i = 0; i < KisTileData::HEIGHT; i++) {
303 for (int j = 0; j < KisTileData::WIDTH; j++) {
305 }
306 }
308}
309
310#ifdef DEAD_TILES_SANITY_CHECK
311
312void KisTile::sanityCheckIsNotDestroyedYet()
313{
314 if (m_lockCounter) {
315 qDebug() << this << ppVar(m_sanityLockedForRead);
316 qDebug() << this << ppVar(m_sanityLockedForWrite);
317 qDebug() << this << ppVar(m_lockCounter);
318
319 KIS_ASSERT(!m_lockCounter || !m_sanityLockedForWrite && "sanityCheckIsNotDestroyedYet() failed");
320 }
321}
322
323void KisTile::sanityCheckIsNotLockedForWrite()
324{
325 if (m_sanityHasBeenDetached.loadAcquire()) {
326 qDebug() << this << ppVar(m_sanityNumCOWHappened);
327 qDebug() << this << ppVar(m_sanityHasBeenDetached);
328 qDebug() << this << ppVar(m_sanityMMHasBeenInitializedManually);
329 qDebug() << this << ppVar(m_sanityIsDead);
330 KIS_ASSERT(0 && "sanityCheckIsNotLockedForWrite() failed");
331 }
332}
333
334#endif
void registerTileChange(KisTile *tile)
void registerTileDeleted(KisTile *tile)
void unblockSwapping()
KisTileData * clone()
void blockSwapping()
static const qint32 HEIGHT
static const qint32 WIDTH
void blockSwapping() const
Definition kis_tile.cc:158
KisTileSP m_nextTile
Definition kis_tile.h:147
void notifyAttachedToDataManager(KisMementoManager *mm)
Definition kis_tile.cc:113
qint32 row() const
Definition kis_tile.h:92
KisTile(qint32 col, qint32 row, KisTileData *defaultTileData, KisMementoManager *mm)
Definition kis_tile.cc:36
void notifyDeadWithoutDetaching()
Definition kis_tile.cc:100
void lockForWrite()
Definition kis_tile.cc:221
QAtomicPointer< KisMementoManager > m_mementoManager
Definition kis_tile.h:149
QMutex m_swapBarrierLock
Definition kis_tile.h:163
KisTileData * m_tileData
Definition kis_tile.h:132
qint32 col() const
Definition kis_tile.h:95
void notifyDetachedFromDataManager()
Definition kis_tile.cc:83
void lockForRead() const
Definition kis_tile.cc:208
void debugDumpTile()
Definition kis_tile.cc:297
void debugPrintInfo()
Definition kis_tile.cc:288
volatile int m_lockCounter
Definition kis_tile.h:134
void init(qint32 col, qint32 row, KisTileData *defaultTileData, KisMementoManager *mm)
Definition kis_tile.cc:17
void safeReleaseOldTileData(KisTileData *td)
Definition kis_tile.cc:194
QRect m_extent
Definition kis_tile.h:142
KisTileData * tileData() const
Definition kis_tile.h:118
void unlockForWrite()
Definition kis_tile.cc:264
void unlockForRead() const
Definition kis_tile.cc:275
qint32 m_col
Definition kis_tile.h:136
qint32 m_row
Definition kis_tile.h:137
void unblockSwapping() const
Definition kis_tile.cc:176
QMutex m_COWMutex
Definition kis_tile.h:157
~KisTile()
Definition kis_tile.cc:60
QStack< KisTileData * > m_oldTileData
Definition kis_tile.h:133
quint8 * data() const
Definition kis_tile.h:85
qint32 pixelSize() const
Definition kis_tile.h:113
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
#define dbgTiles
Definition kis_debug.h:49
#define ppVar(var)
Definition kis_debug.h:155
#define lazyCopying()
Definition kis_tile.cc:219
#define DEBUG_LOG_ACTION(action)
Definition kis_tile.cc:148
#define DEBUG_COWING(newTD)
Definition kis_tile.cc:155