SuperDex Physics C++ API
Loading...
Searching...
No Matches
allocator.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
20
21#include <cstddef>
22#include <type_traits>
23#include <utility>
24
25namespace superdex {
26
27/*********************************************************************************************
28 Macros
29*/
30
31// Define MOCHI_ALLOCATOR_DEBUG to 1 to enable safety checks. Enabled by default in debug builds.
32#ifndef MOCHI_ALLOCATOR_DEBUG
33#define MOCHI_ALLOCATOR_DEBUG MOCHI_DEBUG
34#endif
35
36/*********************************************************************************************
37 Allocator
38*/
39
40/**
41 * @brief Virtual interface class for memory allocation and deallocation.
42 *
43 * This class provides a polymorphic interface for memory allocation operations, similar to
44 * std::pmr::memory_resource, which is not used because of compatibility issues with various
45 * platform/compiler combinations. Derived classes must implement the protected members.
46 */
47class Allocator {
48 public:
49 virtual ~Allocator() = default;
50
51 /**
52 * @brief Allocate memory of the specified size and alignment.
53 *
54 * @param sizeInBytes
55 * @param alignment Must be a power of 2.
56 * @return void*
57 * @throws std::bad_alloc
58 *
59 * @note The caller is responsible for deallocating the memory by calling the deallocate method on
60 * the same Allocator instance, or a compatible Allocator instance.
61 *
62 * @see deallocate
63 * @see is_equal
64 */
65 void* allocate(std::size_t sizeInBytes, std::size_t alignment = alignof(std::max_align_t));
66
67 /**
68 * @brief Deallocate a block of memory that was previously allocated by this Allocator instance or
69 * by a compatible Allocator instance.
70 *
71 * @param ptr Address of the memory block to deallocate.
72 * @param sizeInBytes Must match the size that was passed to the allocate method.
73 * @param alignment Must match the alignment that was passed to the allocate method.
74 *
75 * @see allocate
76 * @see is_equal
77 */
78 void
79 deallocate(void* ptr, std::size_t sizeInBytes, std::size_t alignment = alignof(std::max_align_t));
80
81 /**
82 * @brief Return true if memory allocated by this Allocator instance can be deallocated by the
83 * other Allocator instance, and visa versa.
84 *
85 * @param other
86 * @return bool
87 */
88 bool is_equal(Allocator const& other) const noexcept;
89
90 protected:
91 virtual void* do_allocate(std::size_t sizeInBytes, std::size_t alignment) = 0;
92 virtual void do_deallocate(void* ptr, std::size_t sizeInBytes, std::size_t alignment) = 0;
93 virtual bool do_is_equal(Allocator const& other) const noexcept = 0;
94};
95
96/*********************************************************************************************
97 Default Allocator
98*/
99
100/**
101 * @brief Mochi's default implementation of the Allocator interface.
102 *
103 * This class allows you to allocate memory on any thread and then deallocate it on any thread,
104 * similar to std::pmr::new_delete_resource. All instance of this class are considered to be "equal"
105 * so that memory allocated from one instance can be deallocated by another instance.
106 */
107class DefaultAllocator final : public Allocator {
108 void* do_allocate(size_t sizeInBytes, size_t alignment) override;
109 void do_deallocate(void* ptr, size_t sizeInBytes, size_t alignment) override;
110 bool do_is_equal(Allocator const& other) const noexcept override;
111};
112
113/**
114 * @brief Get an instance of the DefaultAllocator class. Usable in any context.
115 *
116 * @return Allocator*
117 */
119
120/*********************************************************************************************
121 Utilities
122*/
123
124/**
125 * @brief Create a new object of type T using memory allocated by a polymorphic Allocator.
126 *
127 * @tparam T Type of object to create
128 * @tparam A Type of Allocator
129 * @tparam Args Optional types forwarded to the constructor
130 * @param allocator Pointer to an Allocator instance
131 * @param args Optional arguments forwarded to the constructor for type T
132 * @return T* Address of the new object
133 *
134 * @note The caller is responsible for calling Delete with the same Allocator instance, or a
135 * compatible Allocator instance (see Allocator::is_equal).
136 */
137template <class T, class A, class... Args>
138[[nodiscard]] inline T* New(A* allocator, Args&&... args) {
139 static_assert(std::is_base_of_v<Allocator, A>, "Expected an allocator pointer");
140 T* ptr = static_cast<T*>(allocator->allocate(sizeof(T), alignof(T)));
141 new (ptr) T(std::forward<Args>(args)...);
142 return ptr;
143}
144
145/**
146 * @brief Destroy and deallocate an object that was created via New<T>.
147 *
148 * @tparam T Type of object to destroy
149 * @tparam A Type of Allocator
150 * @param allocator The Allocator instance that was previously passed to New<T>
151 * @param ptr Address of the object to destroy
152 */
153template <class T, class A>
154inline void Delete(A* allocator, T* ptr) {
155 static_assert(std::is_base_of_v<Allocator, A>, "Expected an allocator pointer");
156 ptr->~T();
157 allocator->deallocate(ptr, sizeof(T), alignof(T));
158}
159
160} // namespace superdex
161
162#include "allocator_inl.h"
Virtual interface class for memory allocation and deallocation.
Definition allocator.h:47
virtual void do_deallocate(void *ptr, std::size_t sizeInBytes, std::size_t alignment)=0
void * allocate(std::size_t sizeInBytes, std::size_t alignment=alignof(std::max_align_t))
Allocate memory of the specified size and alignment.
void deallocate(void *ptr, std::size_t sizeInBytes, std::size_t alignment=alignof(std::max_align_t))
Deallocate a block of memory that was previously allocated by this Allocator instance or by a compati...
virtual void * do_allocate(std::size_t sizeInBytes, std::size_t alignment)=0
virtual bool do_is_equal(Allocator const &other) const noexcept=0
bool is_equal(Allocator const &other) const noexcept
Return true if memory allocated by this Allocator instance can be deallocated by the other Allocator ...
virtual ~Allocator()=default
Mochi's default implementation of the Allocator interface.
Definition allocator.h:107
#define MOCHI_FORCE_INLINE
T * New(A *allocator, Args &&... args)
Create a new object of type T using memory allocated by a polymorphic Allocator.
Definition allocator.h:138
Allocator * GetDefaultAllocator()
Get an instance of the DefaultAllocator class.
void Delete(A *allocator, T *ptr)
Destroy and deallocate an object that was created via New<T>.
Definition allocator.h:154