summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/object_pool.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/object_pool.h89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/shader_recompiler/object_pool.h b/src/shader_recompiler/object_pool.h
new file mode 100644
index 000000000..7c65bbd92
--- /dev/null
+++ b/src/shader_recompiler/object_pool.h
@@ -0,0 +1,89 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <type_traits>
9
10namespace Shader {
11
12template <typename T, size_t chunk_size = 8192>
13requires std::is_destructible_v<T> class ObjectPool {
14public:
15 ~ObjectPool() {
16 std::unique_ptr<Chunk> tree_owner;
17 Chunk* chunk{&root};
18 while (chunk) {
19 for (size_t obj_id = chunk->free_objects; obj_id < chunk_size; ++obj_id) {
20 chunk->storage[obj_id].object.~T();
21 }
22 tree_owner = std::move(chunk->next);
23 chunk = tree_owner.get();
24 }
25 }
26
27 template <typename... Args>
28 requires std::is_constructible_v<T, Args...> [[nodiscard]] T* Create(Args&&... args) {
29 return std::construct_at(Memory(), std::forward<Args>(args)...);
30 }
31
32 void ReleaseContents() {
33 Chunk* chunk{&root};
34 if (chunk) {
35 const size_t free_objects{chunk->free_objects};
36 if (free_objects == chunk_size) {
37 break;
38 }
39 chunk->free_objects = chunk_size;
40 for (size_t obj_id = free_objects; obj_id < chunk_size; ++obj_id) {
41 chunk->storage[obj_id].object.~T();
42 }
43 chunk = chunk->next.get();
44 }
45 node = &root;
46 }
47
48private:
49 struct NonTrivialDummy {
50 NonTrivialDummy() noexcept {}
51 };
52
53 union Storage {
54 Storage() noexcept {}
55 ~Storage() noexcept {}
56
57 NonTrivialDummy dummy{};
58 T object;
59 };
60
61 struct Chunk {
62 size_t free_objects = chunk_size;
63 std::array<Storage, chunk_size> storage;
64 std::unique_ptr<Chunk> next;
65 };
66
67 [[nodiscard]] T* Memory() {
68 Chunk* const chunk{FreeChunk()};
69 return &chunk->storage[--chunk->free_objects].object;
70 }
71
72 [[nodiscard]] Chunk* FreeChunk() {
73 if (node->free_objects > 0) {
74 return node;
75 }
76 if (node->next) {
77 node = node->next.get();
78 return node;
79 }
80 node->next = std::make_unique<Chunk>();
81 node = node->next.get();
82 return node;
83 }
84
85 Chunk* node{&root};
86 Chunk root;
87};
88
89} // namespace Shader