File indexing completed on 2024-06-23 04:22:03

0001 /*
0002  *  SPDX-FileCopyrightText: 2004 C. Boemann <cbo@boemann.dk>
0003  *            (c) 2009 Dmitry Kazakov <dimula73@gmail.com>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 #ifndef KIS_TILE_H_
0008 #define KIS_TILE_H_
0009 
0010 #include <QReadWriteLock>
0011 
0012 #include <QMutex>
0013 #include <QAtomicPointer>
0014 
0015 #include <QRect>
0016 #include <QStack>
0017 
0018 #include <kis_shared.h>
0019 #include <kis_shared_ptr.h>
0020 
0021 #include "kis_tile_data.h"
0022 #include "kis_tile_data_store.h"
0023 
0024 //#define DEAD_TILES_SANITY_CHECK
0025 
0026 class KisTile;
0027 typedef KisSharedPtr<KisTile> KisTileSP;
0028 
0029 class KisMementoManager;
0030 
0031 
0032 /**
0033  * Provides abstraction to a tile.
0034  * + A tile contains a part of a PaintDevice,
0035  *   but only the individual pixels are accessible
0036  *   and that only via iterators.
0037  * + Actual tile data is stored in KisTileData that can be
0038  *   shared between many tiles
0039  */
0040 class KRITAIMAGE_EXPORT KisTile : public KisShared
0041 {
0042 public:
0043     KisTile(qint32 col, qint32 row,
0044             KisTileData *defaultTileData, KisMementoManager* mm);
0045     KisTile(const KisTile& rhs, qint32 col, qint32 row, KisMementoManager* mm);
0046     KisTile(const KisTile& rhs, KisMementoManager* mm);
0047     KisTile(const KisTile& rhs);
0048     ~KisTile();
0049 
0050     /**
0051      * This method is called by the hash table when the tile is
0052      * disconnected from it. It means that from now on the tile is not
0053      * associated with any particular datamanager. All the users of
0054      * the tile (via shared pointers) may silently finish they work on
0055      * this tile and leave it. No result will be saved. Used for
0056      * threading purposes
0057      */
0058     void notifyDetachedFromDataManager();
0059 
0060     /**
0061      * Sometimes the tile gets replaced with another tile. In this case
0062      * we shouldn't notify memento manager that the tile has died. Just
0063      * forget the link to the manager and bury it in peace.
0064      */
0065     void notifyDeadWithoutDetaching();
0066 
0067     /**
0068      * Called by the hash table to notify that the tile has been attached
0069      * to the data manager.
0070      */
0071     void notifyAttachedToDataManager(KisMementoManager *mm);
0072 
0073 public:
0074 
0075     void debugPrintInfo();
0076     void debugDumpTile();
0077 
0078     void lockForRead() const;
0079     void lockForWrite();
0080     void unlockForWrite();
0081     void unlockForRead() const;
0082 
0083 
0084     /* this allows us work directly on tile's data */
0085     inline quint8 *data() const {
0086         return m_tileData->data();
0087     }
0088     inline void setData(const quint8 *data) {
0089         m_tileData->setData(data);
0090     }
0091 
0092     inline qint32 row() const {
0093         return m_row;
0094     }
0095     inline qint32 col() const {
0096         return m_col;
0097     }
0098 
0099     inline QRect extent() const {
0100         return m_extent;
0101 //QRect(m_col * KisTileData::WIDTH, m_row * KisTileData::HEIGHT,
0102 //                     KisTileData::WIDTH, KisTileData::HEIGHT);
0103     }
0104 
0105     inline KisTileSP next() const {
0106         return m_nextTile;
0107     }
0108 
0109     void setNext(KisTileSP next) {
0110         m_nextTile = next;
0111     }
0112 
0113     inline qint32 pixelSize() const {
0114         /* don't lock here as pixelSize is constant */
0115         return m_tileData->pixelSize();
0116     }
0117 
0118     inline KisTileData*  tileData() const {
0119         return m_tileData;
0120     }
0121 
0122 private:
0123     void init(qint32 col, qint32 row,
0124               KisTileData *defaultTileData, KisMementoManager* mm);
0125 
0126     inline void blockSwapping() const;
0127     inline void unblockSwapping() const;
0128 
0129     inline void safeReleaseOldTileData(KisTileData *td);
0130 
0131 private:
0132     KisTileData *m_tileData;
0133     mutable QStack<KisTileData*> m_oldTileData;
0134     mutable volatile int m_lockCounter;
0135 
0136     qint32 m_col;
0137     qint32 m_row;
0138 
0139     /**
0140      * Added for faster retrieving by processors
0141      */
0142     QRect m_extent;
0143 
0144     /**
0145      * For KisTiledDataManager's hash table
0146      */
0147     KisTileSP m_nextTile;
0148 
0149     QAtomicPointer<KisMementoManager> m_mementoManager;
0150 
0151     /**
0152      * This is a special mutex for guarding copy-on-write
0153      * operations. We do not use lockless way here as it'll
0154      * create too much overhead for the most common operations
0155      * like "read the pointer of m_tileData".
0156      */
0157     QMutex m_COWMutex;
0158 
0159     /**
0160      * This lock is used to ensure no one will read the tile data
0161      * before it has been loaded from to the memory.
0162      */
0163     mutable QMutex m_swapBarrierLock;
0164 
0165 
0166 #ifdef DEAD_TILES_SANITY_CHECK
0167     QAtomicInt m_sanityHasBeenDetached;
0168     QAtomicInt m_sanityIsDead;
0169     QAtomicInt m_sanityMMHasBeenInitializedManually;
0170     QAtomicInt m_sanityNumCOWHappened;
0171     QAtomicInt m_sanityLockedForWrite;
0172     mutable QAtomicInt m_sanityLockedForRead;
0173 
0174     void sanityCheckIsNotDestroyedYet();
0175     void sanityCheckIsNotLockedForWrite();
0176 #endif
0177 
0178 };
0179 
0180 #endif // KIS_TILE_H_
0181