WPILibC++ 2025.1.1
Loading...
Searching...
No Matches
IntrusiveSharedPtr.hpp
Go to the documentation of this file.
1// Copyright (c) Sleipnir contributors
2
3#pragma once
4
5#include <cstddef>
6#include <memory>
7#include <utility>
8
9namespace sleipnir {
10
11/**
12 * A custom intrusive shared pointer implementation without thread
13 * synchronization overhead.
14 *
15 * Types used with this class should have three things:
16 *
17 * 1. A zero-initialized public counter variable that serves as the shared
18 * pointer's reference count.
19 * 2. A free function `void IntrusiveSharedPtrIncRefCount(T*)` that increments
20 * the reference count.
21 * 3. A free function `void IntrusiveSharedPtrDecRefCount(T*)` that decrements
22 * the reference count and deallocates the pointed to object if the reference
23 * count reaches zero.
24 *
25 * @tparam T The type of the object to be reference counted.
26 */
27template <typename T>
29 public:
30 /**
31 * Constructs an empty intrusive shared pointer.
32 */
33 constexpr IntrusiveSharedPtr() noexcept = default;
34
35 /**
36 * Constructs an empty intrusive shared pointer.
37 */
38 constexpr IntrusiveSharedPtr(std::nullptr_t) noexcept {} // NOLINT
39
40 /**
41 * Constructs an intrusive shared pointer from the given pointer and takes
42 * ownership.
43 */
44 explicit constexpr IntrusiveSharedPtr(T* ptr) noexcept : m_ptr{ptr} {
45 if (m_ptr != nullptr) {
46 IntrusiveSharedPtrIncRefCount(m_ptr);
47 }
48 }
49
50 constexpr ~IntrusiveSharedPtr() {
51 if (m_ptr != nullptr) {
52 IntrusiveSharedPtrDecRefCount(m_ptr);
53 }
54 }
55
56 /**
57 * Copy constructs from the given intrusive shared pointer.
58 */
59 constexpr IntrusiveSharedPtr(const IntrusiveSharedPtr<T>& rhs) noexcept
60 : m_ptr{rhs.m_ptr} {
61 if (m_ptr != nullptr) {
62 IntrusiveSharedPtrIncRefCount(m_ptr);
63 }
64 }
65
66 /**
67 * Makes a copy of the given intrusive shared pointer.
68 */
69 constexpr IntrusiveSharedPtr<T>& operator=( // NOLINT
70 const IntrusiveSharedPtr<T>& rhs) noexcept {
71 if (m_ptr == rhs.m_ptr) {
72 return *this;
73 }
74
75 if (m_ptr != nullptr) {
76 IntrusiveSharedPtrDecRefCount(m_ptr);
77 }
78
79 m_ptr = rhs.m_ptr;
80
81 if (m_ptr != nullptr) {
82 IntrusiveSharedPtrIncRefCount(m_ptr);
83 }
84
85 return *this;
86 }
87
88 /**
89 * Move constructs from the given intrusive shared pointer.
90 */
91 constexpr IntrusiveSharedPtr(IntrusiveSharedPtr<T>&& rhs) noexcept
92 : m_ptr{std::exchange(rhs.m_ptr, nullptr)} {}
93
94 /**
95 * Move assigns from the given intrusive shared pointer.
96 */
98 IntrusiveSharedPtr<T>&& rhs) noexcept {
99 if (m_ptr == rhs.m_ptr) {
100 return *this;
101 }
102
103 std::swap(m_ptr, rhs.m_ptr);
104
105 return *this;
106 }
107
108 /**
109 * Returns the internal pointer.
110 */
111 constexpr T* Get() const noexcept { return m_ptr; }
112
113 /**
114 * Returns the object pointed to by the internal pointer.
115 */
116 constexpr T& operator*() const noexcept { return *m_ptr; }
117
118 /**
119 * Returns the internal pointer.
120 */
121 constexpr T* operator->() const noexcept { return m_ptr; }
122
123 /**
124 * Returns true if the internal pointer isn't nullptr.
125 */
126 explicit constexpr operator bool() const noexcept { return m_ptr != nullptr; }
127
128 /**
129 * Returns true if the given intrusive shared pointers point to the same
130 * object.
131 */
132 friend constexpr bool operator==(const IntrusiveSharedPtr<T>& lhs,
133 const IntrusiveSharedPtr<T>& rhs) noexcept {
134 return lhs.m_ptr == rhs.m_ptr;
135 }
136
137 /**
138 * Returns true if the given intrusive shared pointers point to different
139 * objects.
140 */
141 friend constexpr bool operator!=(const IntrusiveSharedPtr<T>& lhs,
142 const IntrusiveSharedPtr<T>& rhs) noexcept {
143 return lhs.m_ptr != rhs.m_ptr;
144 }
145
146 /**
147 * Returns true if the left-hand intrusive shared pointer points to nullptr.
148 */
149 friend constexpr bool operator==(const IntrusiveSharedPtr<T>& lhs,
150 std::nullptr_t) noexcept {
151 return lhs.m_ptr == nullptr;
152 }
153
154 /**
155 * Returns true if the right-hand intrusive shared pointer points to nullptr.
156 */
157 friend constexpr bool operator==(std::nullptr_t,
158 const IntrusiveSharedPtr<T>& rhs) noexcept {
159 return nullptr == rhs.m_ptr;
160 }
161
162 /**
163 * Returns true if the left-hand intrusive shared pointer doesn't point to
164 * nullptr.
165 */
166 friend constexpr bool operator!=(const IntrusiveSharedPtr<T>& lhs,
167 std::nullptr_t) noexcept {
168 return lhs.m_ptr != nullptr;
169 }
170
171 /**
172 * Returns true if the right-hand intrusive shared pointer doesn't point to
173 * nullptr.
174 */
175 friend constexpr bool operator!=(std::nullptr_t,
176 const IntrusiveSharedPtr<T>& rhs) noexcept {
177 return nullptr != rhs.m_ptr;
178 }
179
180 private:
181 T* m_ptr = nullptr;
182};
183
184/**
185 * Constructs an object of type T and wraps it in an intrusive shared pointer
186 * using args as the parameter list for the constructor of T.
187 *
188 * @tparam T Type of object for intrusive shared pointer.
189 * @tparam Args Types of constructor arguments.
190 * @param args Constructor arguments for T.
191 */
192template <typename T, typename... Args>
194 return IntrusiveSharedPtr<T>{new T(std::forward<Args>(args)...)};
195}
196
197/**
198 * Constructs an object of type T and wraps it in an intrusive shared pointer
199 * using alloc as the storage allocator of T and args as the parameter list for
200 * the constructor of T.
201 *
202 * @tparam T Type of object for intrusive shared pointer.
203 * @tparam Alloc Type of allocator for T.
204 * @tparam Args Types of constructor arguments.
205 * @param alloc The allocator for T.
206 * @param args Constructor arguments for T.
207 */
208template <typename T, typename Alloc, typename... Args>
209IntrusiveSharedPtr<T> AllocateIntrusiveShared(Alloc alloc, Args&&... args) {
210 auto ptr = std::allocator_traits<Alloc>::allocate(alloc, sizeof(T));
211 std::allocator_traits<Alloc>::construct(alloc, ptr,
212 std::forward<Args>(args)...);
214}
215
216} // namespace sleipnir
A custom intrusive shared pointer implementation without thread synchronization overhead.
Definition IntrusiveSharedPtr.hpp:28
friend constexpr bool operator==(std::nullptr_t, const IntrusiveSharedPtr< T > &rhs) noexcept
Returns true if the right-hand intrusive shared pointer points to nullptr.
Definition IntrusiveSharedPtr.hpp:157
constexpr IntrusiveSharedPtr< T > & operator=(IntrusiveSharedPtr< T > &&rhs) noexcept
Move assigns from the given intrusive shared pointer.
Definition IntrusiveSharedPtr.hpp:97
constexpr T * Get() const noexcept
Returns the internal pointer.
Definition IntrusiveSharedPtr.hpp:111
friend constexpr bool operator!=(const IntrusiveSharedPtr< T > &lhs, std::nullptr_t) noexcept
Returns true if the left-hand intrusive shared pointer doesn't point to nullptr.
Definition IntrusiveSharedPtr.hpp:166
constexpr IntrusiveSharedPtr< T > & operator=(const IntrusiveSharedPtr< T > &rhs) noexcept
Makes a copy of the given intrusive shared pointer.
Definition IntrusiveSharedPtr.hpp:69
friend constexpr bool operator==(const IntrusiveSharedPtr< T > &lhs, std::nullptr_t) noexcept
Returns true if the left-hand intrusive shared pointer points to nullptr.
Definition IntrusiveSharedPtr.hpp:149
constexpr ~IntrusiveSharedPtr()
Definition IntrusiveSharedPtr.hpp:50
friend constexpr bool operator==(const IntrusiveSharedPtr< T > &lhs, const IntrusiveSharedPtr< T > &rhs) noexcept
Returns true if the given intrusive shared pointers point to the same object.
Definition IntrusiveSharedPtr.hpp:132
constexpr IntrusiveSharedPtr(T *ptr) noexcept
Constructs an intrusive shared pointer from the given pointer and takes ownership.
Definition IntrusiveSharedPtr.hpp:44
constexpr T & operator*() const noexcept
Returns the object pointed to by the internal pointer.
Definition IntrusiveSharedPtr.hpp:116
constexpr IntrusiveSharedPtr() noexcept=default
Constructs an empty intrusive shared pointer.
friend constexpr bool operator!=(std::nullptr_t, const IntrusiveSharedPtr< T > &rhs) noexcept
Returns true if the right-hand intrusive shared pointer doesn't point to nullptr.
Definition IntrusiveSharedPtr.hpp:175
constexpr IntrusiveSharedPtr(const IntrusiveSharedPtr< T > &rhs) noexcept
Copy constructs from the given intrusive shared pointer.
Definition IntrusiveSharedPtr.hpp:59
constexpr T * operator->() const noexcept
Returns the internal pointer.
Definition IntrusiveSharedPtr.hpp:121
constexpr IntrusiveSharedPtr(IntrusiveSharedPtr< T > &&rhs) noexcept
Move constructs from the given intrusive shared pointer.
Definition IntrusiveSharedPtr.hpp:91
friend constexpr bool operator!=(const IntrusiveSharedPtr< T > &lhs, const IntrusiveSharedPtr< T > &rhs) noexcept
Returns true if the given intrusive shared pointers point to different objects.
Definition IntrusiveSharedPtr.hpp:141
auto ptr(T p) -> const void *
Converts p to const void* for pointer formatting.
Definition format.h:3821
Definition Hessian.hpp:18
IntrusiveSharedPtr< T > AllocateIntrusiveShared(Alloc alloc, Args &&... args)
Constructs an object of type T and wraps it in an intrusive shared pointer using alloc as the storage...
Definition IntrusiveSharedPtr.hpp:209
IntrusiveSharedPtr< T > MakeIntrusiveShared(Args &&... args)
Constructs an object of type T and wraps it in an intrusive shared pointer using args as the paramete...
Definition IntrusiveSharedPtr.hpp:193
Implement std::hash so that hash_code can be used in STL containers.
Definition PointerIntPair.h:280
WPI_BASIC_JSON_TPL_DECLARATION void swap(wpi::WPI_BASIC_JSON_TPL &j1, wpi::WPI_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< wpi::WPI_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< wpi::WPI_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.h:5258
decltype(nullptr) nullptr_t
Definition base.h:312