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

0001 /*
0002  *  SPDX-FileCopyrightText: 2010 Dmitry Kazakov <dimula73@gmail.com>
0003  *  SPDX-FileCopyrightText: 2018 Andrey Kamakin <a.kamakin@icloud.com>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #ifndef KIS_TILE_DATA_STORE_ITERATORS_H_
0009 #define KIS_TILE_DATA_STORE_ITERATORS_H_
0010 
0011 #include "kis_tile_data.h"
0012 #include "kis_debug.h"
0013 
0014 /**
0015  * KisTileDataStoreIterator,
0016  * KisTileDataStoreReverseIterator,
0017  * KisTileDataStoreClockIterator
0018  * - are general iterators for the contents of KisTileDataStore.
0019  * The store starts holding a lock when returns one of such
0020  * iterators, so no one will be able to change the list while
0021  * you are iterating.
0022  *
0023  * But be careful! You can't change the list while iterating either,
0024  * because it can invalidate the iterator. This is a general rule.
0025  */
0026 
0027 
0028 class KisTileDataStoreIterator
0029 {
0030 public:
0031     KisTileDataStoreIterator(ConcurrentMap<int, KisTileData*> &map, KisTileDataStore *store)
0032         : m_map(map),
0033           m_store(store)
0034     {
0035         m_iterator.setMap(m_map);
0036     }
0037 
0038     inline KisTileData* peekNext()
0039     {
0040         return m_iterator.getValue();
0041     }
0042 
0043     inline KisTileData* next()
0044     {
0045         KisTileData *current = m_iterator.getValue();
0046         m_iterator.next();
0047         return current;
0048     }
0049 
0050     inline bool hasNext() const
0051     {
0052         return m_iterator.isValid();
0053     }
0054 
0055     inline bool trySwapOut(KisTileData *td)
0056     {
0057         if (td == m_iterator.getValue()) {
0058             m_iterator.next();
0059         }
0060 
0061         return m_store->trySwapTileData(td);
0062     }
0063 
0064 private:
0065     ConcurrentMap<int, KisTileData*> &m_map;
0066     ConcurrentMap<int, KisTileData*>::Iterator m_iterator;
0067     KisTileDataStore *m_store;
0068 };
0069 
0070 class KisTileDataStoreReverseIterator : public KisTileDataStoreIterator
0071 {
0072 public:
0073     KisTileDataStoreReverseIterator(ConcurrentMap<int, KisTileData*> &map, KisTileDataStore *store)
0074         : KisTileDataStoreIterator(map, store)
0075     {
0076     }
0077 };
0078 
0079 class KisTileDataStoreClockIterator
0080 {
0081 public:
0082     KisTileDataStoreClockIterator(ConcurrentMap<int, KisTileData*> &map,
0083                                   int startIndex,
0084                                   KisTileDataStore *store)
0085         : m_map(map),
0086           m_store(store)
0087     {
0088         m_iterator.setMap(m_map);
0089         m_finalPosition = m_iterator.getValue()->m_tileNumber;
0090         m_startItem = m_map.get(startIndex);
0091 
0092         if (m_iterator.getValue() == m_startItem || !m_startItem) {
0093             m_startItem = 0;
0094             m_endReached = true;
0095         } else {
0096             while (m_iterator.getValue() != m_startItem) {
0097                 m_iterator.next();
0098             }
0099             m_endReached = false;
0100         }
0101     }
0102 
0103     inline KisTileData* peekNext()
0104     {
0105         if (!m_iterator.isValid()) {
0106             m_iterator.setMap(m_map);
0107             m_endReached = true;
0108         }
0109 
0110         return m_iterator.getValue();
0111     }
0112 
0113     inline KisTileData* next()
0114     {
0115         if (!m_iterator.isValid()) {
0116             m_iterator.setMap(m_map);
0117             m_endReached = true;
0118         }
0119 
0120         KisTileData *current = m_iterator.getValue();
0121         m_iterator.next();
0122         return current;
0123     }
0124 
0125     inline bool hasNext() const
0126     {
0127         return !(m_endReached && m_iterator.getValue() == m_startItem);
0128     }
0129 
0130     inline bool trySwapOut(KisTileData *td)
0131     {
0132         if (td == m_iterator.getValue()) {
0133             m_iterator.next();
0134         }
0135 
0136         return m_store->trySwapTileData(td);
0137     }
0138 
0139 private:
0140     friend class KisTileDataStore;
0141     inline int getFinalPosition()
0142     {
0143         if (!m_iterator.isValid()) {
0144             return m_finalPosition;
0145         }
0146 
0147         return m_iterator.getValue()->m_tileNumber;
0148     }
0149 
0150 private:
0151     ConcurrentMap<int, KisTileData*> &m_map;
0152     ConcurrentMap<int, KisTileData*>::Iterator m_iterator;
0153     KisTileData *m_startItem;
0154     bool m_endReached;
0155     KisTileDataStore *m_store;
0156     int m_finalPosition;
0157 };
0158 
0159 #endif /* KIS_TILE_DATA_STORE_ITERATORS_H_ */
0160