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