xrpld
Loading...
Searching...
No Matches
IntrusivePointer.h
1#pragma once
2
3#include <concepts>
4#include <cstdint>
5#include <type_traits>
6#include <utility>
7
8namespace xrpl {
9
10//------------------------------------------------------------------------------
11
19
28
35
42
43//------------------------------------------------------------------------------
44//
45
46template <class T>
49
50//------------------------------------------------------------------------------
51
66template <class T>
68{
69public:
70 SharedIntrusive() = default;
71
72 template <CAdoptTag TAdoptTag>
73 SharedIntrusive(T* p, TAdoptTag) noexcept;
74
76
77 template <class TT>
78 // TODO: convertible_to isn't quite right. That include a static castable.
79 // Find the right concept.
80 requires std::convertible_to<TT*, T*>
82
84
85 template <class TT>
86 requires std::convertible_to<TT*, T*>
88 SharedIntrusive<TT>&& rhs); // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
89
92
93 bool
95
96 bool
98
99 template <class TT>
100 requires std::convertible_to<TT*, T*>
103
106
107 template <class TT>
108 requires std::convertible_to<TT*, T*>
111 SharedIntrusive<TT>&& rhs); // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
112
116 template <CAdoptTag TAdoptTag = SharedIntrusiveAdoptIncrementStrongTag>
117 void
118 adopt(T* p);
119
121
125 template <class TT>
127
131 template <class TT>
133
137 template <class TT>
139
143 template <class TT>
145
146 T&
147 operator*() const noexcept;
148
149 T*
150 operator->() const noexcept;
151
152 explicit
153 operator bool() const noexcept;
154
158 void
160
162 [[nodiscard]] T*
163 get() const;
164
166 [[nodiscard]] std::size_t
167 useCount() const;
168
169 template <class TT, class... Args>
170 friend SharedIntrusive<TT>
171 makeSharedIntrusive(Args&&... args);
172
173 template <class TT>
174 friend class SharedIntrusive;
175
176 template <class TT>
177 friend class SharedWeakUnion;
178
179 template <class TT>
180 friend class WeakIntrusive;
181
182private:
184 [[nodiscard]] T*
186
191 void
193
197 void
199
205 T*
207
209 T* ptr_{nullptr};
210};
211
212//------------------------------------------------------------------------------
213
220template <class T>
222{
223public:
224 WeakIntrusive() = default;
225
227
229
231
232 // There is no move constructor from a strong intrusive ptr because
233 // moving would be move expensive than copying in this case (the strong
234 // ref would need to be decremented)
235 WeakIntrusive(SharedIntrusive<T> const&& rhs) = delete;
236
237 // Since there are no current use cases for copy assignment in
238 // WeakIntrusive, we delete this operator to simplify the implementation. If
239 // a need arises in the future, we can reintroduce it with proper
240 // consideration."
242 operator=(WeakIntrusive const&) = delete;
243
244 template <class TT>
245 requires std::convertible_to<TT*, T*>
248
250 void
251 adopt(T* ptr);
252
254
260 lock() const;
261
263 [[nodiscard]] bool
264 expired() const;
265
270 void
272
273private:
274 T* ptr_ = nullptr;
275
281 void
283};
284
285//------------------------------------------------------------------------------
286
297
298template <class T>
300{
301 // Tagged pointer. Low bit determines if this is a strong or a weak
302 // pointer. The low bit must be masked to zero when converting back to a
303 // pointer. If the low bit is '1', this is a weak pointer.
304 static_assert(alignof(T) >= 2, "Bad alignment: Combo pointer requires low bit to be zero");
305
306public:
307 SharedWeakUnion() = default;
308
310
311 template <class TT>
312 requires std::convertible_to<TT*, T*>
314
316
317 template <class TT>
318 requires std::convertible_to<TT*, T*>
320 SharedIntrusive<TT>&& rhs); // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
321
324
325 template <class TT>
326 requires std::convertible_to<TT*, T*>
329
330 template <class TT>
331 requires std::convertible_to<TT*, T*>
334 SharedIntrusive<TT>&& rhs); // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
335
337
342 [[nodiscard]] SharedIntrusive<T>
343 getStrong() const;
344
348 explicit
349 operator bool() const noexcept;
350
354 void
356
360 [[nodiscard]] T*
361 get() const;
362
366 [[nodiscard]] std::size_t
367 useCount() const;
368
370 [[nodiscard]] bool
371 expired() const;
372
376 [[nodiscard]] SharedIntrusive<T>
377 lock() const;
378
380 [[nodiscard]] bool
381 isStrong() const;
382
384 [[nodiscard]] bool
385 isWeak() const;
386
393 bool
395
401 bool
403
404private:
405 // Tagged pointer. Low bit determines if this is a strong or a weak
406 // pointer. The low bit must be masked to zero when converting back to a
407 // pointer. If the low bit is '1', this is a weak pointer.
408 std::uintptr_t tp_{0};
409 static constexpr std::uintptr_t kTagMask = 1;
411
412private:
415 [[nodiscard]] T*
417
418 enum class RefStrength { Strong, Weak };
421 void
423
427
431 void
433};
434
435//------------------------------------------------------------------------------
436
443template <class TT, class... Args>
445makeSharedIntrusive(Args&&... args)
446{
447 auto p = new TT(std::forward<Args>(args)...);
448
449 static_assert(
450 noexcept(SharedIntrusive<TT>(
452 "SharedIntrusive constructor should not throw or this can leak "
453 "memory");
454
456}
457
458//------------------------------------------------------------------------------
459
460namespace intr_ptr {
461template <class T>
463
464template <class T>
466
467template <class T>
469
470template <class T, class... A>
472makeShared(A&&... args)
473{
475}
476
477template <class T, class TT>
480{
482}
483
484template <class T, class TT>
487{
489}
490} // namespace intr_ptr
491} // namespace xrpl
A shared intrusive pointer class that supports weak pointers.
SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive< TT > const &rhs)
Create a new SharedIntrusive by dynamically casting the pointer controlled by the rhs param.
SHAMapTreeNode * unsafeGetRawPtr() const
SharedIntrusive & operator=(SharedIntrusive< TT > const &rhs)
bool operator==(std::nullptr_t) const
SharedIntrusive(SharedIntrusive< TT > const &rhs)
SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive< TT > const &rhs)
Create a new SharedIntrusive by statically casting the pointer controlled by the rhs param.
void unsafeSetRawPtr(SHAMapTreeNode *p)
SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive< TT > &&rhs)
Create a new SharedIntrusive by dynamically casting the pointer controlled by the rhs param.
SHAMapTreeNode * unsafeExchange(SHAMapTreeNode *p)
SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive< TT > &&rhs)
Create a new SharedIntrusive by statically casting the pointer controlled by the rhs param.
void adopt(T *p)
Adopt the raw pointer.
SharedIntrusive & operator=(SharedIntrusive &&rhs)
void unsafeReleaseAndStore(SHAMapTreeNode *next)
SharedIntrusive(SharedIntrusive< TT > &&rhs)
SharedIntrusive(SharedIntrusive const &rhs)
SharedIntrusive(T *p, TAdoptTag) noexcept
friend SharedIntrusive< TT > makeSharedIntrusive(Args &&... args)
bool operator!=(std::nullptr_t) const
SharedIntrusive & operator=(SharedIntrusive< TT > &&rhs)
SharedIntrusive & operator=(SharedIntrusive const &rhs)
T & operator*() const noexcept
SharedIntrusive(SharedIntrusive &&rhs)
A combination of a strong and a weak intrusive pointer stored in the space of a single pointer.
void unsafeSetRawPtr(std::nullptr_t)
Set the raw pointer and tag bit to all zeros (strong null pointer).
SharedWeakUnion(SharedIntrusive< TT > const &rhs)
SharedWeakUnion(SharedWeakUnion const &rhs)
static constexpr std::uintptr_t kPtrMask
bool expired() const
Return true if there is a non-zero strong count.
SharedWeakUnion(SharedWeakUnion &&rhs)
SharedWeakUnion(SharedIntrusive< TT > &&rhs)
void reset()
Set the pointer to null, decrement the appropriate ref count, and run the appropriate release action.
static constexpr std::uintptr_t kTagMask
void unsafeSetRawPtr(T *p, RefStrength rs)
Set the raw pointer and tag bit directly.
T * unsafeGetRawPtr() const
Return the raw pointer held by this object.
T * get() const
If this is a strong pointer, return the raw pointer.
SharedWeakUnion & operator=(SharedIntrusive< TT > const &rhs)
bool convertToStrong()
If this is a weak pointer, attempt to convert it to a strong pointer.
SharedIntrusive< T > lock() const
If this is a strong pointer, return the strong pointer.
SharedWeakUnion & operator=(SharedIntrusive< TT > &&rhs)
SharedWeakUnion & operator=(SharedWeakUnion const &rhs)
void unsafeReleaseNoStore()
Decrement the appropriate ref count, and run the appropriate release action.
bool convertToWeak()
If this is a strong pointer, attempt to convert it to a weak pointer.
bool isStrong() const
Return true is this represents a strong pointer.
std::size_t useCount() const
If this is a strong pointer, return the strong count.
bool isWeak() const
Return true is this represents a weak pointer.
SharedIntrusive< T > getStrong() const
Return a strong pointer if this is already a strong pointer (i.e.
A weak intrusive pointer class for the SharedIntrusive pointer class.
WeakIntrusive(SharedIntrusive< T > const &&rhs)=delete
void unsafeReleaseNoStore()
Decrement the weak count.
WeakIntrusive(WeakIntrusive const &rhs)
void adopt(T *ptr)
Adopt the raw pointer and increment the weak count.
WeakIntrusive(SharedIntrusive< T > const &rhs)
SharedIntrusive< T > lock() const
Get a strong pointer from the weak pointer, if possible.
WeakIntrusive & operator=(SharedIntrusive< TT > const &rhs)
WeakIntrusive & operator=(WeakIntrusive const &)=delete
bool expired() const
Return true if the strong count is zero.
WeakIntrusive(WeakIntrusive &&rhs)
WeakIntrusive()=default
void reset()
Set the pointer to null and decrement the weak count.
T declval(T... args)
T forward(T... args)
T is_same_v
STL namespace.
SharedWeakUnion< T > SharedWeakUnionPtr
SharedPtr< T > dynamicPointerCast(TT const &v)
SharedPtr< T > staticPointerCast(TT const &v)
SharedIntrusive< T > SharedPtr
WeakIntrusive< T > WeakPtr
SharedPtr< T > makeShared(A &&... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
SharedIntrusive< TT > makeSharedIntrusive(Args &&... args)
Create a shared intrusive pointer.
Tag to create an intrusive pointer from another intrusive pointer by using a dynamic cast.
When creating or adopting a raw pointer, controls whether the strong count is incremented or not.
When creating or adopting a raw pointer, controls whether the strong count is incremented or not.
Tag to create an intrusive pointer from another intrusive pointer by using a static cast.