object_pool.h 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <memory>
  6. #include <type_traits>
  7. namespace Shader {
  8. template <typename T, size_t chunk_size = 8192>
  9. requires std::is_destructible_v<T> class ObjectPool {
  10. public:
  11. ~ObjectPool() {
  12. std::unique_ptr<Chunk> tree_owner;
  13. Chunk* chunk{&root};
  14. while (chunk) {
  15. for (size_t obj_id = chunk->free_objects; obj_id < chunk_size; ++obj_id) {
  16. chunk->storage[obj_id].object.~T();
  17. }
  18. tree_owner = std::move(chunk->next);
  19. chunk = tree_owner.get();
  20. }
  21. }
  22. template <typename... Args>
  23. requires std::is_constructible_v<T, Args...> [[nodiscard]] T* Create(Args&&... args) {
  24. return std::construct_at(Memory(), std::forward<Args>(args)...);
  25. }
  26. void ReleaseContents() {
  27. Chunk* chunk{&root};
  28. if (chunk) {
  29. const size_t free_objects{chunk->free_objects};
  30. if (free_objects == chunk_size) {
  31. break;
  32. }
  33. chunk->free_objects = chunk_size;
  34. for (size_t obj_id = free_objects; obj_id < chunk_size; ++obj_id) {
  35. chunk->storage[obj_id].object.~T();
  36. }
  37. chunk = chunk->next.get();
  38. }
  39. node = &root;
  40. }
  41. private:
  42. struct NonTrivialDummy {
  43. NonTrivialDummy() noexcept {}
  44. };
  45. union Storage {
  46. Storage() noexcept {}
  47. ~Storage() noexcept {}
  48. NonTrivialDummy dummy{};
  49. T object;
  50. };
  51. struct Chunk {
  52. size_t free_objects = chunk_size;
  53. std::array<Storage, chunk_size> storage;
  54. std::unique_ptr<Chunk> next;
  55. };
  56. [[nodiscard]] T* Memory() {
  57. Chunk* const chunk{FreeChunk()};
  58. return &chunk->storage[--chunk->free_objects].object;
  59. }
  60. [[nodiscard]] Chunk* FreeChunk() {
  61. if (node->free_objects > 0) {
  62. return node;
  63. }
  64. if (node->next) {
  65. node = node->next.get();
  66. return node;
  67. }
  68. node->next = std::make_unique<Chunk>();
  69. node = node->next.get();
  70. return node;
  71. }
  72. Chunk* node{&root};
  73. Chunk root;
  74. };
  75. } // namespace Shader