// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include namespace Common { class FreeRegionManager { public: explicit FreeRegionManager() = default; ~FreeRegionManager() = default; void SetAddressSpace(void* start, size_t size) { this->FreeBlock(start, size); } std::pair FreeBlock(void* block_ptr, size_t size) { std::scoped_lock lk(m_mutex); // Check to see if we are adjacent to any regions. auto start_address = reinterpret_cast(block_ptr); auto end_address = start_address + size; auto it = m_free_regions.find({start_address - 1, end_address + 1}); // If we are, join with them, ensuring we stay in bounds. if (it != m_free_regions.end()) { start_address = std::min(start_address, it->lower()); end_address = std::max(end_address, it->upper()); } // Free the relevant region. m_free_regions.insert({start_address, end_address}); // Return the adjusted pointers. block_ptr = reinterpret_cast(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(block_ptr); m_free_regions.subtract({address, address + size}); } private: std::mutex m_mutex; boost::icl::interval_set m_free_regions; }; } // namespace Common