WPILibC++ 2025.1.1
Loading...
Searching...
No Matches
virtual_memory.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_VIRTUAL_MEMORY_HPP_INCLUDED
5#define WPI_MEMORY_VIRTUAL_MEMORY_HPP_INCLUDED
6
7/// \file
8/// Virtual memory api and (low-level) allocator classes.
9
10#include <cstddef>
11#include <type_traits>
12
14#include "detail/utility.hpp"
15#include "config.hpp"
16
17#if WPI_MEMORY_EXTERN_TEMPLATE
18#include "allocator_traits.hpp"
19#endif
20
21namespace wpi
22{
23 namespace memory
24 {
25 namespace detail
26 {
28 {
29 void operator()(std::ptrdiff_t amount);
30 };
31
33 virtual_memory_allocator_leak_checker)
34 } // namespace detail
35
36 /// The page size of the virtual memory.
37 /// All virtual memory allocations must be multiple of this size.
38 /// It is usually 4KiB.
39 /// \ingroup memory_allocator
40 /// \deprecated use \ref get_virtual_memory_page_size instead.
41 extern const std::size_t virtual_memory_page_size;
42
43 /// \returns the page size of the virtual memory.
44 /// All virtual memory allocations must be multiple of this size.
45 /// It is usually 4KiB.
46 /// \ingroup memory_allocator
47 std::size_t get_virtual_memory_page_size() noexcept;
48
49 /// Reserves virtual memory.
50 /// \effects Reserves the given number of pages.
51 /// Each page is \ref virtual_memory_page_size big.
52 /// \returns The address of the first reserved page,
53 /// or \c nullptr in case of error.
54 /// \note The memory may not be used, it must first be commited.
55 /// \ingroup memory_allocator
56 void* virtual_memory_reserve(std::size_t no_pages) noexcept;
57
58 /// Releases reserved virtual memory.
59 /// \effects Returns previously reserved pages to the system.
60 /// \requires \c pages must come from a previous call to \ref virtual_memory_reserve with the same \c calc_no_pages,
61 /// it must not be \c nullptr.
62 /// \ingroup memory_allocator
63 void virtual_memory_release(void* pages, std::size_t no_pages) noexcept;
64
65 /// Commits reserved virtual memory.
66 /// \effects Marks \c calc_no_pages pages starting at the given address available for use.
67 /// \returns The beginning of the committed area, i.e. \c memory, or \c nullptr in case of error.
68 /// \requires The memory must be previously reserved.
69 /// \ingroup memory_allocator
70 void* virtual_memory_commit(void* memory, std::size_t no_pages) noexcept;
71
72 /// Decommits commited virtual memory.
73 /// \effects Puts commited memory back in the reserved state.
74 /// \requires \c memory must come from a previous call to \ref virtual_memory_commit with the same \c calc_no_pages
75 /// it must not be \c nullptr.
76 /// \ingroup memory_allocator
77 void virtual_memory_decommit(void* memory, std::size_t no_pages) noexcept;
78
79 /// A stateless RawAllocator that allocates memory using the virtual memory allocation functions.
80 /// It does not prereserve any memory and will always reserve and commit combined.
81 /// \ingroup memory_allocator
83 : WPI_EBO(detail::global_leak_checker<detail::virtual_memory_allocator_leak_handler>)
84 {
85 public:
86 using is_stateful = std::false_type;
87
88 virtual_memory_allocator() noexcept = default;
90 ~virtual_memory_allocator() noexcept = default;
91
93 {
94 return *this;
95 }
96
97 /// \effects A RawAllocator allocation function.
98 /// It uses \ref virtual_memory_reserve followed by \ref virtual_memory_commit for the allocation.
99 /// The number of pages allocated will be the minimum to hold \c size continuous bytes,
100 /// i.e. \c size will be rounded up to the next multiple.
101 /// If debug fences are activated, one additional page before and after the memory will be allocated.
102 /// \returns A pointer to a node, it will never be \c nullptr.
103 /// It will always be aligned on a fence boundary, regardless of the alignment parameter.
104 /// \throws An exception of type \ref out_of_memory or whatever is thrown by its handler if the allocation fails.
105 void* allocate_node(std::size_t size, std::size_t alignment);
106
107 /// \effects A RawAllocator deallocation function.
108 /// It calls \ref virtual_memory_decommit followed by \ref virtual_memory_release for the deallocation.
109 void deallocate_node(void* node, std::size_t size, std::size_t alignment) noexcept;
110
111 /// \returns The maximum node size by returning the maximum value.
112 std::size_t max_node_size() const noexcept;
113
114 /// \returns The maximum alignment which is the same as the \ref virtual_memory_page_size.
115 std::size_t max_alignment() const noexcept;
116 };
117
118#if WPI_MEMORY_EXTERN_TEMPLATE
119 extern template class allocator_traits<virtual_memory_allocator>;
120#endif
121
122 struct memory_block;
123 struct allocator_info;
124
125 /// A BlockAllocator that reserves virtual memory and commits it part by part.
126 /// It is similar to \ref memory_stack but does not support growing and uses virtual memory,
127 /// also meant for big blocks not small allocations.
128 /// \ingroup memory_allocator
130 {
131 public:
132 /// \effects Creates it giving it the block size and the total number of blocks it can allocate.
133 /// It reserves enough virtual memory for <tt>block_size * no_blocks</tt>.
134 /// \requires \c block_size must be non-zero and a multiple of the \ref virtual_memory_page_size.
135 /// \c no_blocks must be bigger than \c 1.
136 /// \throws \ref out_of_memory if it cannot reserve the virtual memory.
137 explicit virtual_block_allocator(std::size_t block_size, std::size_t no_blocks);
138
139 /// \effects Releases the reserved virtual memory.
141
142 /// @{
143 /// \effects Moves the block allocator, it transfers ownership over the reserved area.
144 /// This does not invalidate any memory blocks.
146 : cur_(other.cur_), end_(other.end_), block_size_(other.block_size_)
147 {
148 other.cur_ = other.end_ = nullptr;
149 other.block_size_ = 0;
150 }
151
153 {
155 swap(*this, tmp);
156 return *this;
157 }
158 /// @}
159
160 /// \effects Swaps the ownership over the reserved memory.
161 /// This does not invalidate any memory blocks.
163 {
164 detail::adl_swap(a.cur_, b.cur_);
165 detail::adl_swap(a.end_, b.end_);
166 detail::adl_swap(a.block_size_, b.block_size_);
167 }
168
169 /// \effects Allocates a new memory block by committing the next \ref next_block_size() number of bytes.
170 /// \returns The \ref memory_block committed.
171 /// \throws \ref out_of_memory if it cannot commit the memory or the \ref capacity_left() is exhausted.
173
174 /// \effects Deallocates the last allocated memory block by decommitting it.
175 /// This block will be returned again on the next call to \ref allocate_block().
176 /// \requires \c block must be the current top block of the memory,
177 /// this is guaranteed by \ref memory_arena.
178 void deallocate_block(memory_block block) noexcept;
179
180 /// \returns The next block size, this is the block size of the constructor.
181 std::size_t next_block_size() const noexcept
182 {
183 return block_size_;
184 }
185
186 /// \returns The number of blocks that can be committed until it runs out of memory.
187 std::size_t capacity_left() const noexcept
188 {
189 return static_cast<std::size_t>(end_ - cur_) / block_size_;
190 }
191
192 private:
193 allocator_info info() noexcept;
194
195 char * cur_, *end_;
196 std::size_t block_size_;
197 };
198 } // namespace memory
199} // namespace wpi
200
201#endif //WPI_MEMORY_VIRTUAL_MEMORY_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
A BlockAllocator that reserves virtual memory and commits it part by part.
Definition virtual_memory.hpp:130
std::size_t capacity_left() const noexcept
Definition virtual_memory.hpp:187
friend void swap(virtual_block_allocator &a, virtual_block_allocator &b) noexcept
Definition virtual_memory.hpp:162
std::size_t next_block_size() const noexcept
Definition virtual_memory.hpp:181
void deallocate_block(memory_block block) noexcept
virtual_block_allocator & operator=(virtual_block_allocator &&other) noexcept
Definition virtual_memory.hpp:152
virtual_block_allocator(std::size_t block_size, std::size_t no_blocks)
A stateless RawAllocator that allocates memory using the virtual memory allocation functions.
Definition virtual_memory.hpp:84
~virtual_memory_allocator() noexcept=default
void * allocate_node(std::size_t size, std::size_t alignment)
virtual_memory_allocator() noexcept=default
void deallocate_node(void *node, std::size_t size, std::size_t alignment) noexcept
std::false_type is_stateful
Definition virtual_memory.hpp:86
std::size_t max_node_size() const noexcept
Configuration macros.
#define WPI_MEMORY_GLOBAL_LEAK_CHECKER(handler, var_name)
Definition debug_helpers.hpp:220
void virtual_memory_release(void *pages, std::size_t no_pages) noexcept
Releases reserved virtual memory.
void * virtual_memory_commit(void *memory, std::size_t no_pages) noexcept
Commits reserved virtual memory.
const std::size_t virtual_memory_page_size
The page size of the virtual memory.
void virtual_memory_decommit(void *memory, std::size_t no_pages) noexcept
Decommits commited virtual memory.
std::size_t get_virtual_memory_page_size() noexcept
void * virtual_memory_reserve(std::size_t no_pages) noexcept
Reserves virtual memory.
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
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