Iros
 
Loading...
Searching...
No Matches
object_pool.h
Go to the documentation of this file.
1#pragma once
2
3#include "di/assert/prelude.h"
10#include "di/util/prelude.h"
11#include "iris/core/error.h"
12
13namespace iris {
14namespace detail {
15 struct InternalObjectTag : di::IntrusiveForwardListTag<InternalObjectTag> {
16 template<typename U>
17 constexpr static auto is_sized(di::InPlaceType<U>) -> bool {
18 return true;
19 }
20 };
21
22 struct InternalObjectFreed : di::IntrusiveForwardListNode<InternalObjectTag> {};
23
24 template<typename T>
31}
32
40template<typename T, di::concepts::FallibleAllocator Alloc = di::DefaultAllocator>
42public:
43 static auto create(usize requested_capacity) -> Expected<ObjectPool> {
44 auto pool = ObjectPool {};
45
46 auto [storage, effective_capacity] =
47 TRY(di::allocate_many<detail::InternalObject<T>>(pool.m_allocator, requested_capacity));
48 pool.m_storage = storage;
49 pool.m_capacity = effective_capacity;
50
51 di::uninitialized_default_construct(pool.m_storage, pool.m_storage + pool.m_capacity);
52
53 di::for_each(pool.m_storage, pool.m_storage + pool.m_capacity, [&](detail::InternalObject<T>& object) {
54 di::construct_at(&object.freed);
55 pool.m_free_list.push_front(object.freed);
56 });
57
58 return pool;
59 }
60
61 ObjectPool() = default;
62
64 : m_free_list(di::move(other.m_free_list))
65 , m_storage(di::exchange(other.m_storage, nullptr))
66 , m_capacity(di::exchange(other.m_capacity, 0))
67 , m_allocator(di::move(other.m_allocator)) {
68 ASSERT_EQ(m_capacity, m_free_list.size());
69 }
70
72
73 auto operator=(ObjectPool&& other) -> ObjectPool& {
74 clear();
75
76 m_free_list = di::move(other.m_free_list);
77 m_storage = di::exchange(other.m_storage, nullptr);
78 m_capacity = di::exchange(other.m_capacity, 0);
79 m_allocator = di::move(other.m_allocator);
80
81 return *this;
82 }
83
84 void clear() {
85 ASSERT_EQ(m_free_list.size(), m_capacity);
86
87 if (m_capacity) {
88 // NOTE: all objects must have been freed, so there is no need to call destructors.
89 di::deallocate_many<detail::InternalObject<T>>(m_allocator, m_storage, m_capacity);
90 }
91 }
92
94 if (m_free_list.empty()) {
96 }
97 auto* freed_pointer = &*m_free_list.pop_front();
98
99 // NOTE: the freed object should have the same memory location as the internal object, so this *should* be safe.
100 auto* internal_object = reinterpret_cast<detail::InternalObject<T>*>(freed_pointer);
101 di::destroy_at(&internal_object->freed);
102 di::construct_at(&internal_object->object);
103 return internal_object->object;
104 }
105
106 void deallocate(T& object) {
107 // NOTE: the object should have the same memory location as the internal object, so this *should* be safe.
108 auto* internal_object = reinterpret_cast<detail::InternalObject<T>*>(&object);
109 di::destroy_at(&internal_object->object);
110
111 di::construct_at(&internal_object->freed);
112 m_free_list.push_front(internal_object->freed);
113 }
114
115private:
117 detail::InternalObject<T>* m_storage { nullptr };
118 usize m_capacity { 0 };
119 [[no_unique_address]] Alloc m_allocator {};
120};
121}
#define ASSERT_EQ
Definition assert_binary.h:84
Definition forward_list_node.h:9
Definition forward_list_forward_declaration.h:12
Definition unexpected.h:14
~ObjectPool()
Definition object_pool.h:71
auto allocate() -> Expected< T & >
Definition object_pool.h:93
void deallocate(T &object)
Definition object_pool.h:106
ObjectPool()=default
ObjectPool(ObjectPool &&other)
Definition object_pool.h:63
auto operator=(ObjectPool &&other) -> ObjectPool &
Definition object_pool.h:73
void clear()
Definition object_pool.h:84
static auto create(usize requested_capacity) -> Expected< ObjectPool >
Definition object_pool.h:43
#define TRY
Definition monad_try.h:23
size_t usize
Definition integers.h:33
Definition zstring_parser.h:9
constexpr auto exchange(T &object, U &&new_value) -> T
Definition exchange.h:8
constexpr auto for_each
Definition for_each.h:31
constexpr auto destroy_at
Definition destroy_at.h:24
constexpr auto deallocate_many
Definition deallocate_many.h:28
constexpr auto uninitialized_default_construct
Definition uninitialized_default_construct.h:34
constexpr auto allocate_many
Definition allocate_many.h:48
constexpr auto construct_at
Definition construct_at.h:27
Definition object_pool.h:14
Definition cxx_init.cpp:12
@ NotEnoughMemory
Definition error.h:59
di::vocab::Expected< T, di::platform::GenericCode > Expected
Definition error.h:324
Definition forward_list.h:17
Definition in_place_type.h:5
Definition object_pool.h:22
Definition object_pool.h:15
static constexpr auto is_sized(di::InPlaceType< U >) -> bool
Definition object_pool.h:17
Definition object_pool.h:25
InternalObjectFreed freed
Definition object_pool.h:29
InternalObject()
Definition object_pool.h:26
T object
Definition object_pool.h:28