File indexing completed on 2024-06-23 04:22:00
0001 /* 0002 * SPDX-FileCopyrightText: 2010 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef __KIS_CHUNK_LIST_H 0008 #define __KIS_CHUNK_LIST_H 0009 0010 #include <QLinkedList> 0011 #include "kritaimage_export.h" 0012 0013 #define MiB (1ULL << 20) 0014 0015 #define DEFAULT_STORE_SIZE (4096*MiB) 0016 #define DEFAULT_SLAB_SIZE (64*MiB) 0017 0018 0019 //#define DEBUG_SLAB_FAILS 0020 0021 #ifdef DEBUG_SLAB_FAILS 0022 0023 #define WINDOW_SIZE 2000 0024 #define DECLARE_FAIL_COUNTER() quint64 __failCount 0025 #define INIT_FAIL_COUNTER() __failCount = 0 0026 #define START_COUNTING() quint64 __numSteps = 0 0027 #define REGISTER_STEP() if(++__numSteps > WINDOW_SIZE) {__numSteps=0; __failCount++;} 0028 #define REGISTER_FAIL() __failCount++ 0029 #define DEBUG_FAIL_COUNTER() qInfo() << "Slab fail count:\t" << __failCount 0030 0031 #else 0032 0033 #define DECLARE_FAIL_COUNTER() 0034 #define INIT_FAIL_COUNTER() 0035 #define START_COUNTING() 0036 #define REGISTER_STEP() 0037 #define REGISTER_FAIL() 0038 #define DEBUG_FAIL_COUNTER() 0039 0040 #endif /* DEBUG_SLAB_FAILS */ 0041 0042 0043 0044 class KisChunkData; 0045 0046 typedef QLinkedList<KisChunkData> KisChunkDataList; 0047 typedef KisChunkDataList::iterator KisChunkDataListIterator; 0048 0049 class KRITAIMAGE_EXPORT KisChunkData 0050 { 0051 public: 0052 KisChunkData(quint64 begin, quint64 size) 0053 { 0054 setChunk(begin, size); 0055 } 0056 0057 inline void setChunk(quint64 begin, quint64 size) { 0058 m_begin = begin; 0059 m_end = begin + size - 1; 0060 } 0061 0062 inline quint64 size() const { 0063 return m_end - m_begin +1; 0064 } 0065 0066 bool operator== (const KisChunkData& other) const 0067 { 0068 Q_ASSERT(m_begin!=other.m_begin || m_end==other.m_end); 0069 0070 /** 0071 * Chunks cannot overlap, so it is enough to check 0072 * the beginning of the interval only 0073 */ 0074 return m_begin == other.m_begin; 0075 } 0076 0077 quint64 m_begin; 0078 quint64 m_end; 0079 }; 0080 0081 class KRITAIMAGE_EXPORT KisChunk 0082 { 0083 public: 0084 KisChunk() {} 0085 0086 KisChunk(KisChunkDataListIterator iterator) 0087 : m_iterator(iterator) 0088 { 0089 } 0090 0091 inline quint64 begin() const { 0092 return m_iterator->m_begin; 0093 } 0094 0095 inline quint64 end() const { 0096 return m_iterator->m_end; 0097 } 0098 0099 inline quint64 size() const { 0100 return m_iterator->size(); 0101 } 0102 0103 inline KisChunkDataListIterator position() { 0104 return m_iterator; 0105 } 0106 0107 inline const KisChunkData& data() { 0108 return *m_iterator; 0109 } 0110 0111 private: 0112 KisChunkDataListIterator m_iterator; 0113 }; 0114 0115 0116 class KRITAIMAGE_EXPORT KisChunkAllocator 0117 { 0118 public: 0119 KisChunkAllocator(quint64 slabSize = DEFAULT_SLAB_SIZE, 0120 quint64 storeSize = DEFAULT_STORE_SIZE); 0121 ~KisChunkAllocator(); 0122 0123 inline quint64 numChunks() const { 0124 return m_list.size(); 0125 } 0126 0127 KisChunk getChunk(quint64 size); 0128 void freeChunk(KisChunk chunk); 0129 0130 void debugChunks(); 0131 bool sanityCheck(bool pleaseCrash = true); 0132 qreal debugFragmentation(bool toStderr = true); 0133 0134 private: 0135 bool tryInsertChunk(KisChunkDataList &list, 0136 KisChunkDataListIterator &iterator, 0137 quint64 size); 0138 0139 private: 0140 quint64 m_storeMaxSize; 0141 quint64 m_storeSlabSize; 0142 0143 0144 KisChunkDataList m_list; 0145 KisChunkDataListIterator m_iterator; 0146 quint64 m_storeSize; 0147 DECLARE_FAIL_COUNTER() 0148 }; 0149 0150 #endif /* __KIS_CHUNK_ALLOCATOR_H */ 0151