30 #include "MemoryAllocator.h" 31 #include "STDAllocator.h" 32 #include "DebugUtilities.h" 57 class VariableSizeAllocationsManager
60 typedef size_t OffsetType;
61 static constexpr OffsetType InvalidOffset =
static_cast<OffsetType
>(-1);
67 using TFreeBlocksByOffsetMap =
70 std::less<OffsetType>,
71 STDAllocatorRawMem<std::pair<const OffsetType, FreeBlockInfo>>
75 using TFreeBlocksBySizeMap =
76 std::multimap<OffsetType,
77 TFreeBlocksByOffsetMap::iterator,
78 std::less<OffsetType>,
79 STDAllocatorRawMem<std::pair<const OffsetType, TFreeBlocksByOffsetMap::iterator>>
88 TFreeBlocksBySizeMap::iterator OrderBySizeIt;
90 FreeBlockInfo(OffsetType _Size) : Size(_Size){}
94 VariableSizeAllocationsManager(OffsetType MaxSize, IMemoryAllocator &Allocator) :
97 m_FreeBlocksByOffset( STD_ALLOCATOR_RAW_MEM(TFreeBlocksByOffsetMap::value_type, Allocator,
"Allocator for map<OffsetType, FreeBlockInfo>") ),
98 m_FreeBlocksBySize( STD_ALLOCATOR_RAW_MEM(TFreeBlocksBySizeMap::value_type, Allocator,
"Allocator for multimap<OffsetType, TFreeBlocksByOffsetMap::iterator>") )
101 AddNewBlock(0, m_MaxSize);
108 ~VariableSizeAllocationsManager()
111 if( !m_FreeBlocksByOffset.empty() || !m_FreeBlocksBySize.empty() )
113 VERIFY(m_FreeBlocksByOffset.size() == 1,
"Single free block is expected");
114 VERIFY(m_FreeBlocksByOffset.begin()->first == 0,
"Head chunk offset is expected to be 0");
115 VERIFY(m_FreeBlocksByOffset.begin()->second.Size == m_MaxSize,
"Head chunk size is expected to be ", m_MaxSize);
116 VERIFY_EXPR(m_FreeBlocksByOffset.begin()->second.OrderBySizeIt == m_FreeBlocksBySize.begin());
117 VERIFY(m_FreeBlocksBySize.size() == m_FreeBlocksByOffset.size(),
"Sizes of the two maps must be equal");
119 VERIFY(m_FreeBlocksBySize.size() == 1,
"Single free block is expected");
120 VERIFY(m_FreeBlocksBySize.begin()->first == m_MaxSize,
"Head chunk size is expected to be ", m_MaxSize);
121 VERIFY(m_FreeBlocksBySize.begin()->second == m_FreeBlocksByOffset.begin(),
"Incorrect first block");
126 VariableSizeAllocationsManager(VariableSizeAllocationsManager&& rhs) :
127 m_FreeBlocksByOffset(
std::move(rhs.m_FreeBlocksByOffset)),
128 m_FreeBlocksBySize(
std::move(rhs.m_FreeBlocksBySize)),
129 m_MaxSize(rhs.m_MaxSize),
130 m_FreeSize(rhs.m_FreeSize)
136 VariableSizeAllocationsManager& operator = (VariableSizeAllocationsManager&& rhs) =
default;
137 VariableSizeAllocationsManager(
const VariableSizeAllocationsManager&) =
delete;
138 VariableSizeAllocationsManager& operator = (
const VariableSizeAllocationsManager&) =
delete;
140 OffsetType Allocate(OffsetType Size)
142 VERIFY_EXPR(Size != 0);
143 if(m_FreeSize < Size)
144 return InvalidOffset;
149 auto SmallestBlockItIt = m_FreeBlocksBySize.lower_bound(Size);
150 if(SmallestBlockItIt == m_FreeBlocksBySize.end())
151 return InvalidOffset;
153 auto SmallestBlockIt = SmallestBlockItIt->second;
154 VERIFY_EXPR(Size <= SmallestBlockIt->second.Size);
155 VERIFY_EXPR(SmallestBlockIt->second.Size == SmallestBlockItIt->first);
164 auto Offset = SmallestBlockIt->first;
165 auto NewOffset = Offset + Size;
166 auto NewSize = SmallestBlockIt->second.Size - Size;
167 VERIFY_EXPR(SmallestBlockItIt == SmallestBlockIt->second.OrderBySizeIt);
168 m_FreeBlocksBySize.erase(SmallestBlockItIt);
169 m_FreeBlocksByOffset.erase(SmallestBlockIt);
172 AddNewBlock(NewOffset, NewSize);
183 void Free(OffsetType Offset, OffsetType Size)
185 VERIFY_EXPR(Offset+Size <= m_MaxSize);
190 auto NextBlockIt = m_FreeBlocksByOffset.upper_bound(Offset);
193 auto LowBnd = m_FreeBlocksByOffset.lower_bound(Offset);
195 VERIFY_EXPR(LowBnd == NextBlockIt);
199 VERIFY_EXPR(NextBlockIt == m_FreeBlocksByOffset.end() || Offset+Size <= NextBlockIt->first);
200 auto PrevBlockIt = NextBlockIt;
201 if(PrevBlockIt != m_FreeBlocksByOffset.begin())
205 VERIFY_EXPR(Offset >= PrevBlockIt->first + PrevBlockIt->second.Size);
208 PrevBlockIt = m_FreeBlocksByOffset.end();
210 OffsetType NewSize, NewOffset;
211 if(PrevBlockIt != m_FreeBlocksByOffset.end() && Offset == PrevBlockIt->first + PrevBlockIt->second.Size)
217 NewSize = PrevBlockIt->second.Size + Size;
218 NewOffset = PrevBlockIt->first;
220 if (NextBlockIt != m_FreeBlocksByOffset.end() && Offset + Size == NextBlockIt->first)
226 NewSize += NextBlockIt->second.Size;
227 m_FreeBlocksBySize.erase(PrevBlockIt->second.OrderBySizeIt);
228 m_FreeBlocksBySize.erase(NextBlockIt->second.OrderBySizeIt);
231 m_FreeBlocksByOffset.erase(PrevBlockIt, NextBlockIt);
239 m_FreeBlocksBySize.erase(PrevBlockIt->second.OrderBySizeIt);
240 m_FreeBlocksByOffset.erase(PrevBlockIt);
243 else if (NextBlockIt != m_FreeBlocksByOffset.end() && Offset + Size == NextBlockIt->first)
249 NewSize = Size + NextBlockIt->second.Size;
251 m_FreeBlocksBySize.erase(NextBlockIt->second.OrderBySizeIt);
252 m_FreeBlocksByOffset.erase(NextBlockIt);
264 AddNewBlock(NewOffset, NewSize);
272 OffsetType GetMaxSize()
const{
return m_MaxSize;}
273 bool IsFull()
const{
return m_FreeSize==0; };
274 bool IsEmpty()
const{
return m_FreeSize==m_MaxSize; };
275 OffsetType GetFreeSize()
const{
return m_FreeSize;}
278 size_t DbgGetNumFreeBlocks()
const{
return m_FreeBlocksByOffset.size();}
282 void AddNewBlock(OffsetType Offset, OffsetType Size)
284 auto NewBlockIt = m_FreeBlocksByOffset.emplace(Offset, Size);
285 VERIFY_EXPR(NewBlockIt.second);
286 auto OrderIt = m_FreeBlocksBySize.emplace(Size, NewBlockIt.first);
287 NewBlockIt.first->second.OrderBySizeIt = OrderIt;
294 OffsetType TotalFreeSize = 0;
296 auto BlockIt = m_FreeBlocksByOffset.begin();
297 auto PrevBlockIt = m_FreeBlocksByOffset.end();
298 VERIFY_EXPR(m_FreeBlocksByOffset.size() == m_FreeBlocksBySize.size());
299 while (BlockIt != m_FreeBlocksByOffset.end())
301 VERIFY_EXPR(BlockIt->first >= 0 && BlockIt->first + BlockIt->second.Size <= m_MaxSize);
302 VERIFY_EXPR(BlockIt == BlockIt->second.OrderBySizeIt->second);
303 VERIFY_EXPR(BlockIt->second.Size == BlockIt->second.OrderBySizeIt->first);
308 VERIFY(PrevBlockIt == m_FreeBlocksByOffset.end() || BlockIt->first > PrevBlockIt->first + PrevBlockIt->second.Size,
"Unmerged adjacent or overlapping blocks detected" );
309 TotalFreeSize += BlockIt->second.Size;
311 PrevBlockIt = BlockIt;
315 auto OrderIt = m_FreeBlocksBySize.begin();
316 while (OrderIt != m_FreeBlocksBySize.end())
318 VERIFY_EXPR(OrderIt->first == OrderIt->second->second.Size);
322 VERIFY_EXPR(TotalFreeSize == m_FreeSize);
326 TFreeBlocksByOffsetMap m_FreeBlocksByOffset;
327 TFreeBlocksBySizeMap m_FreeBlocksBySize;
329 const OffsetType m_MaxSize = 0;
330 OffsetType m_FreeSize = 0;
Graphics engine namespace.
Definition: AdaptiveFixedBlockAllocator.h:30
Definition: AdvancedMath.h:316