WPILibC++ 2025.1.1
Loading...
Searching...
No Matches
free_list.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_DETAILL_FREE_LIST_HPP_INCLUDED
5#define WPI_MEMORY_DETAILL_FREE_LIST_HPP_INCLUDED
6
7#include <cstddef>
8#include <cstdint>
9
10#include "align.hpp"
11#include "utility.hpp"
12#include "../config.hpp"
13
14namespace wpi
15{
16 namespace memory
17 {
18 namespace detail
19 {
20 // stores free blocks for a memory pool
21 // memory blocks are fragmented and stored in a list
22 // debug: fills memory and uses a bigger node_size for fence memory
24 {
25 public:
26 // minimum element size
27 static constexpr auto min_element_size = sizeof(char*);
28 // alignment
29 static constexpr auto min_element_alignment = alignof(char*);
30
31 // minimal size of the block that needs to be inserted
32 static constexpr std::size_t min_block_size(std::size_t node_size,
33 std::size_t number_of_nodes)
34 {
36 * number_of_nodes;
37 }
38
39 //=== constructor ===//
40 free_memory_list(std::size_t node_size) noexcept;
41
42 // calls other constructor plus insert
43 free_memory_list(std::size_t node_size, void* mem, std::size_t size) noexcept;
44
46 ~free_memory_list() noexcept = default;
47
48 free_memory_list& operator=(free_memory_list&& other) noexcept;
49
50 friend void swap(free_memory_list& a, free_memory_list& b) noexcept;
51
52 //=== insert/allocation/deallocation ===//
53 // inserts a new memory block, by splitting it up and setting the links
54 // does not own memory!
55 // mem must be aligned for alignment()
56 // pre: size != 0
57 void insert(void* mem, std::size_t size) noexcept;
58
59 // returns the usable size
60 // i.e. how many memory will be actually inserted and usable on a call to insert()
61 std::size_t usable_size(std::size_t size) const noexcept
62 {
63 // Round down to next multiple of node size.
64 return (size / node_size_) * node_size_;
65 }
66
67 // returns a single block from the list
68 // pre: !empty()
69 void* allocate() noexcept;
70
71 // returns a memory block big enough for n bytes
72 // might fail even if capacity is sufficient
73 void* allocate(std::size_t n) noexcept;
74
75 // deallocates a single block
76 void deallocate(void* ptr) noexcept;
77
78 // deallocates multiple blocks with n bytes total
79 void deallocate(void* ptr, std::size_t n) noexcept;
80
81 //=== getter ===//
82 std::size_t node_size() const noexcept
83 {
84 return node_size_;
85 }
86
87 // alignment of all nodes
88 std::size_t alignment() const noexcept;
89
90 // number of nodes remaining
91 std::size_t capacity() const noexcept
92 {
93 return capacity_;
94 }
95
96 bool empty() const noexcept
97 {
98 return first_ == nullptr;
99 }
100
101 private:
102 void insert_impl(void* mem, std::size_t size) noexcept;
103
104 char* first_;
105 std::size_t node_size_, capacity_;
106 };
107
109
110 // same as above but keeps the nodes ordered
111 // this allows array allocations, that is, consecutive nodes
112 // debug: fills memory and uses a bigger node_size for fence memory
114 {
115 public:
116 // minimum element size
117 static constexpr auto min_element_size = sizeof(char*);
118 // alignment
119 static constexpr auto min_element_alignment = alignof(char*);
120
121 // minimal size of the block that needs to be inserted
122 static constexpr std::size_t min_block_size(std::size_t node_size,
123 std::size_t number_of_nodes)
124 {
126 * number_of_nodes;
127 }
128
129 //=== constructor ===//
130 ordered_free_memory_list(std::size_t node_size) noexcept;
131
132 ordered_free_memory_list(std::size_t node_size, void* mem,
133 std::size_t size) noexcept
135 {
136 insert(mem, size);
137 }
138
140
141 ~ordered_free_memory_list() noexcept = default;
142
144 {
146 swap(*this, tmp);
147 return *this;
148 }
149
151
152 //=== insert/allocation/deallocation ===//
153 // inserts a new memory block, by splitting it up and setting the links
154 // does not own memory!
155 // mem must be aligned for alignment()
156 // pre: size != 0
157 void insert(void* mem, std::size_t size) noexcept;
158
159 // returns the usable size
160 // i.e. how many memory will be actually inserted and usable on a call to insert()
161 std::size_t usable_size(std::size_t size) const noexcept
162 {
163 // Round down to next multiple of node size.
164 return (size / node_size_) * node_size_;
165 }
166
167 // returns a single block from the list
168 // pre: !empty()
169 void* allocate() noexcept;
170
171 // returns a memory block big enough for n bytes (!, not nodes)
172 // might fail even if capacity is sufficient
173 void* allocate(std::size_t n) noexcept;
174
175 // deallocates a single block
176 void deallocate(void* ptr) noexcept;
177
178 // deallocates multiple blocks with n bytes total
179 void deallocate(void* ptr, std::size_t n) noexcept;
180
181 //=== getter ===//
182 std::size_t node_size() const noexcept
183 {
184 return node_size_;
185 }
186
187 // alignment of all nodes
188 std::size_t alignment() const noexcept;
189
190 // number of nodes remaining
191 std::size_t capacity() const noexcept
192 {
193 return capacity_;
194 }
195
196 bool empty() const noexcept
197 {
198 return capacity_ == 0u;
199 }
200
201 private:
202 // returns previous pointer
203 char* insert_impl(void* mem, std::size_t size) noexcept;
204
205 char* begin_node() noexcept;
206 char* end_node() noexcept;
207
208 std::uintptr_t begin_proxy_, end_proxy_;
209 std::size_t node_size_, capacity_;
210 char * last_dealloc_, *last_dealloc_prev_;
211 };
212
214
215#if WPI_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK
216 // use ordered version to allow pointer check
219#else
222#endif
223 } // namespace detail
224 } // namespace memory
225} // namespace wpi
226
227#endif // WPI_MEMORY_DETAILL_FREE_LIST_HPP_INCLUDED
Definition free_list.hpp:24
free_memory_list(std::size_t node_size) noexcept
void insert(void *mem, std::size_t size) noexcept
std::size_t node_size() const noexcept
Definition free_list.hpp:82
static constexpr auto min_element_size
Definition free_list.hpp:27
void deallocate(void *ptr) noexcept
free_memory_list(std::size_t node_size, void *mem, std::size_t size) noexcept
free_memory_list(free_memory_list &&other) noexcept
bool empty() const noexcept
Definition free_list.hpp:96
std::size_t capacity() const noexcept
Definition free_list.hpp:91
std::size_t usable_size(std::size_t size) const noexcept
Definition free_list.hpp:61
static constexpr std::size_t min_block_size(std::size_t node_size, std::size_t number_of_nodes)
Definition free_list.hpp:32
static constexpr auto min_element_alignment
Definition free_list.hpp:29
std::size_t alignment() const noexcept
static constexpr std::size_t min_block_size(std::size_t node_size, std::size_t number_of_nodes)
Definition free_list.hpp:122
friend void swap(ordered_free_memory_list &a, ordered_free_memory_list &b) noexcept
std::size_t alignment() const noexcept
void insert(void *mem, std::size_t size) noexcept
std::size_t capacity() const noexcept
Definition free_list.hpp:191
bool empty() const noexcept
Definition free_list.hpp:196
ordered_free_memory_list(std::size_t node_size, void *mem, std::size_t size) noexcept
Definition free_list.hpp:132
std::size_t usable_size(std::size_t size) const noexcept
Definition free_list.hpp:161
static constexpr auto min_element_size
Definition free_list.hpp:117
std::size_t node_size() const noexcept
Definition free_list.hpp:182
ordered_free_memory_list(ordered_free_memory_list &&other) noexcept
static constexpr auto min_element_alignment
Definition free_list.hpp:119
ordered_free_memory_list(std::size_t node_size) noexcept
Configuration macros.
auto ptr(T p) -> const void *
Converts p to const void* for pointer formatting.
Definition format.h:3821
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
std::remove_reference< T >::type && move(T &&arg) noexcept
Definition utility.hpp:25
void swap(free_memory_list &a, free_memory_list &b) noexcept
Memory namespace.
Definition heap_allocator.hpp:20
Foonathan namespace.
Definition ntcore_cpp.h:26