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