| | |
| | |
| |
|
| | #pragma once |
| |
|
| | #include <mutex> |
| | #include <boost/icl/interval_set.hpp> |
| |
|
| | namespace Common { |
| |
|
| | class FreeRegionManager { |
| | public: |
| | explicit FreeRegionManager() = default; |
| | ~FreeRegionManager() = default; |
| |
|
| | void SetAddressSpace(void* start, size_t size) { |
| | this->FreeBlock(start, size); |
| | } |
| |
|
| | std::pair<void*, size_t> FreeBlock(void* block_ptr, size_t size) { |
| | std::scoped_lock lk(m_mutex); |
| |
|
| | |
| | auto start_address = reinterpret_cast<uintptr_t>(block_ptr); |
| | auto end_address = start_address + size; |
| | auto it = m_free_regions.find({start_address - 1, end_address + 1}); |
| |
|
| | |
| | if (it != m_free_regions.end()) { |
| | start_address = std::min(start_address, it->lower()); |
| | end_address = std::max(end_address, it->upper()); |
| | } |
| |
|
| | |
| | m_free_regions.insert({start_address, end_address}); |
| |
|
| | |
| | block_ptr = reinterpret_cast<void*>(start_address); |
| | size = end_address - start_address; |
| | return {block_ptr, size}; |
| | } |
| |
|
| | void AllocateBlock(void* block_ptr, size_t size) { |
| | std::scoped_lock lk(m_mutex); |
| |
|
| | auto address = reinterpret_cast<uintptr_t>(block_ptr); |
| | m_free_regions.subtract({address, address + size}); |
| | } |
| |
|
| | private: |
| | std::mutex m_mutex; |
| | boost::icl::interval_set<uintptr_t> m_free_regions; |
| | }; |
| |
|
| | } |
| |
|