// Copyright 2021 yuzu Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once #include #include namespace Shader { template requires std::is_destructible_v class ObjectPool { public: ~ObjectPool() { std::unique_ptr tree_owner; Chunk* chunk{&root}; while (chunk) { for (size_t obj_id = chunk->free_objects; obj_id < chunk_size; ++obj_id) { chunk->storage[obj_id].object.~T(); } tree_owner = std::move(chunk->next); chunk = tree_owner.get(); } } template requires std::is_constructible_v [[nodiscard]] T* Create(Args&&... args) { return std::construct_at(Memory(), std::forward(args)...); } void ReleaseContents() { Chunk* chunk{&root}; if (chunk) { const size_t free_objects{chunk->free_objects}; if (free_objects == chunk_size) { break; } chunk->free_objects = chunk_size; for (size_t obj_id = free_objects; obj_id < chunk_size; ++obj_id) { chunk->storage[obj_id].object.~T(); } chunk = chunk->next.get(); } node = &root; } private: struct NonTrivialDummy { NonTrivialDummy() noexcept {} }; union Storage { Storage() noexcept {} ~Storage() noexcept {} NonTrivialDummy dummy{}; T object; }; struct Chunk { size_t free_objects = chunk_size; std::array storage; std::unique_ptr next; }; [[nodiscard]] T* Memory() { Chunk* const chunk{FreeChunk()}; return &chunk->storage[--chunk->free_objects].object; } [[nodiscard]] Chunk* FreeChunk() { if (node->free_objects > 0) { return node; } if (node->next) { node = node->next.get(); return node; } node->next = std::make_unique(); node = node->next.get(); return node; } Chunk* node{&root}; Chunk root; }; } // namespace Shader