WPILibC++ 2025.1.1
Loading...
Searching...
No Matches
static_allocator.hpp
Go to the documentation of this file.
1// Copyright (C) 2015-2023 Jonathan Müller and foonathan/memory contributors
2// SPDX-License-Identifier: Zlib
3
4#ifndef WPI_MEMORY_STATIC_ALLOCATOR_HPP_INCLUDED
5#define WPI_MEMORY_STATIC_ALLOCATOR_HPP_INCLUDED
6
7/// \file
8/// Allocators using a static, fixed-sized storage.
9
10#include <type_traits>
11
12#include "detail/align.hpp"
13#include "detail/assert.hpp"
15#include "detail/utility.hpp"
16#include "config.hpp"
17
18#if WPI_MEMORY_EXTERN_TEMPLATE
19#include "allocator_traits.hpp"
20#endif
21
22namespace wpi
23{
24 namespace memory
25 {
26 /// Storage for a \ref static_allocator.
27 /// Its constructor will take a reference to it and use it for its allocation.
28 /// The storage type is simply a \c char array aligned for maximum alignment.
29 /// \note It is not allowed to access the memory of the storage.
30 /// \ingroup memory_allocator
31 template <std::size_t Size>
33 {
34 alignas(detail::max_alignment) char storage[Size];
35 };
36
37 static_assert(sizeof(static_allocator_storage<1024>) == 1024, "");
38 static_assert(alignof(static_allocator_storage<1024>) == detail::max_alignment, "");
39
40 struct allocator_info;
41
42 /// A stateful RawAllocator that uses a fixed sized storage for the allocations.
43 /// It works on a \ref static_allocator_storage and uses its memory for all allocations.
44 /// Deallocations are not supported, memory cannot be marked as freed.<br>
45 /// \note It is not allowed to share an \ref static_allocator_storage between multiple \ref static_allocator objects.
46 /// \ingroup memory_allocator
48 {
49 public:
50 using is_stateful = std::true_type;
51
52 /// \effects Creates it by passing it a \ref static_allocator_storage by reference.
53 /// It will take the address of the storage and use its memory for the allocation.
54 /// \requires The storage object must live as long as the allocator object.
55 /// It must not be shared between multiple allocators,
56 /// i.e. the object must not have been passed to a constructor before.
57 template <std::size_t Size>
59 : stack_(&storage), end_(stack_.top() + Size)
60 {
61 }
62
63 /// \effects A RawAllocator allocation function.
64 /// It uses the specified \ref static_allocator_storage.
65 /// \returns A pointer to a node, it will never be \c nullptr.
66 /// \throws An exception of type \ref out_of_memory or whatever is thrown by its handler if the storage is exhausted.
67 void* allocate_node(std::size_t size, std::size_t alignment);
68
69 /// \effects A RawAllocator deallocation function.
70 /// It does nothing, deallocation is not supported by this allocator.
71 void deallocate_node(void*, std::size_t, std::size_t) noexcept {}
72
73 /// \returns The maximum node size which is the capacity remaining inside the \ref static_allocator_storage.
74 std::size_t max_node_size() const noexcept
75 {
76 return static_cast<std::size_t>(end_ - stack_.top());
77 }
78
79 /// \returns The maximum possible value since there is no alignment restriction
80 /// (except indirectly through the size of the \ref static_allocator_storage).
81 std::size_t max_alignment() const noexcept
82 {
83 return std::size_t(-1);
84 }
85
86 private:
87 allocator_info info() const noexcept;
88
89 detail::fixed_memory_stack stack_;
90 const char* end_;
91 };
92
93#if WPI_MEMORY_EXTERN_TEMPLATE
94 extern template class allocator_traits<static_allocator>;
95#endif
96
97 struct memory_block;
98
99 /// A BlockAllocator that allocates the blocks from a fixed size storage.
100 /// It works on a \ref static_allocator_storage and uses it for all allocations,
101 /// deallocations are only allowed in reversed order which is guaranteed by \ref memory_arena.
102 /// \note It is not allowed to share an \ref static_allocator_storage between multiple \ref static_allocator objects.
103 /// \ingroup memory_allocator
105 {
106 public:
107 /// \effects Creates it by passing it the block size and a \ref static_allocator_storage by reference.
108 /// It will take the address of the storage and use it to allocate \c block_size'd blocks.
109 /// \requires The storage object must live as long as the allocator object.
110 /// It must not be shared between multiple allocators,
111 /// i.e. the object must not have been passed to a constructor before.
112 /// The size of the \ref static_allocator_storage must be a multiple of the (non-null) block size.
113 template <std::size_t Size>
114 static_block_allocator(std::size_t block_size,
115 static_allocator_storage<Size>& storage) noexcept
116 : cur_(static_cast<char*>(static_cast<void*>(&storage))),
117 end_(cur_ + Size),
118 block_size_(block_size)
119 {
120 WPI_MEMORY_ASSERT(block_size <= Size);
121 WPI_MEMORY_ASSERT(Size % block_size == 0u);
122 }
123
124 ~static_block_allocator() noexcept = default;
125
126 /// @{
127 /// \effects Moves the block allocator, it transfers ownership over the \ref static_allocator_storage.
128 /// This does not invalidate any memory blocks.
130 : cur_(other.cur_), end_(other.end_), block_size_(other.block_size_)
131 {
132 other.cur_ = other.end_ = nullptr;
133 other.block_size_ = 0;
134 }
135
137 {
139 swap(*this, tmp);
140 return *this;
141 }
142 /// @}
143
144 /// \effects Swaps the ownership over the \ref static_allocator_storage.
145 /// This does not invalidate any memory blocks.
147 {
148 detail::adl_swap(a.cur_, b.cur_);
149 detail::adl_swap(a.end_, b.end_);
150 detail::adl_swap(a.block_size_, b.block_size_);
151 }
152
153 /// \effects Allocates a new block by returning the \ref next_block_size() bytes.
154 /// \returns The new memory block.
156
157 /// \effects Deallocates the last memory block by marking the block as free again.
158 /// This block will be returned again by the next call to \ref allocate_block().
159 /// \requires \c block must be the current top block of the memory,
160 /// this is guaranteed by \ref memory_arena.
161 void deallocate_block(memory_block block) noexcept;
162
163 /// \returns The next block size, this is the size passed to the constructor.
164 std::size_t next_block_size() const noexcept
165 {
166 return block_size_;
167 }
168
169 private:
170 allocator_info info() const noexcept;
171
172 char * cur_, *end_;
173 std::size_t block_size_;
174 };
175 } // namespace memory
176} // namespace wpi
177
178#endif //WPI_MEMORY_STATIC_ALLOCATOR_HPP_INCLUDED
The default specialization of the wpi::memory::allocator_traits.
The default specialization of the allocator_traits for a RawAllocator.
Definition allocator_traits.hpp:292
char * top() const noexcept
Definition memory_stack.hpp:107
A stateful RawAllocator that uses a fixed sized storage for the allocations.
Definition static_allocator.hpp:48
static_allocator(static_allocator_storage< Size > &storage) noexcept
Definition static_allocator.hpp:58
void * allocate_node(std::size_t size, std::size_t alignment)
std::size_t max_node_size() const noexcept
Definition static_allocator.hpp:74
std::true_type is_stateful
Definition static_allocator.hpp:50
void deallocate_node(void *, std::size_t, std::size_t) noexcept
Definition static_allocator.hpp:71
std::size_t max_alignment() const noexcept
Definition static_allocator.hpp:81
A BlockAllocator that allocates the blocks from a fixed size storage.
Definition static_allocator.hpp:105
~static_block_allocator() noexcept=default
friend void swap(static_block_allocator &a, static_block_allocator &b) noexcept
Definition static_allocator.hpp:146
static_block_allocator & operator=(static_block_allocator &&other) noexcept
Definition static_allocator.hpp:136
static_block_allocator(std::size_t block_size, static_allocator_storage< Size > &storage) noexcept
Definition static_allocator.hpp:114
void deallocate_block(memory_block block) noexcept
std::size_t next_block_size() const noexcept
Definition static_allocator.hpp:164
Configuration macros.
detail namespace with internal helper functions
Definition input_adapters.h:32
Implement std::hash so that hash_code can be used in STL containers.
Definition PointerIntPair.h:280
void adl_swap(T &a, T &b) noexcept
Definition utility.hpp:60
constexpr std::size_t max_alignment
Definition align.hpp:42
std::remove_reference< T >::type && move(T &&arg) noexcept
Definition utility.hpp:25
Memory namespace.
Definition heap_allocator.hpp:20
Foonathan namespace.
Definition ntcore_cpp.h:26
void swap(expected< T, E > &lhs, expected< T, E > &rhs) noexcept(noexcept(lhs.swap(rhs)))
Definition expected:2438
Contains information about an allocator.
Definition error.hpp:23
A memory block.
Definition memory_arena.hpp:28
Storage for a static_allocator.
Definition static_allocator.hpp:33
char storage[Size]
Definition static_allocator.hpp:34
#define WPI_MEMORY_ASSERT(Expr)
Definition assert.hpp:46