rippled
Loading...
Searching...
No Matches
IntrusivePointer.h
1#ifndef XRPL_BASICS_INTRUSIVEPOINTER_H_INCLUDED
2#define XRPL_BASICS_INTRUSIVEPOINTER_H_INCLUDED
3
4#include <concepts>
5#include <cstdint>
6#include <type_traits>
7#include <utility>
8
9namespace ripple {
10
11//------------------------------------------------------------------------------
12
20
29
36
43
44//------------------------------------------------------------------------------
45//
46
47template <class T>
50
51//------------------------------------------------------------------------------
52
67template <class T>
69{
70public:
71 SharedIntrusive() = default;
72
73 template <CAdoptTag TAdoptTag>
74 SharedIntrusive(T* p, TAdoptTag) noexcept;
75
77
78 template <class TT>
79 // TODO: convertible_to isn't quite right. That include a static castable.
80 // Find the right concept.
83
85
86 template <class TT>
89
92
93 bool
95
96 bool
98
99 template <class TT>
103
106
107 template <class TT>
111
115 template <CAdoptTag TAdoptTag = SharedIntrusiveAdoptIncrementStrongTag>
116 void
117 adopt(T* p);
118
120
124 template <class TT>
127 SharedIntrusive<TT> const& rhs);
128
132 template <class TT>
134
138 template <class TT>
141 SharedIntrusive<TT> const& rhs);
142
146 template <class TT>
148
149 T&
150 operator*() const noexcept;
151
152 T*
153 operator->() const noexcept;
154
155 explicit
156 operator bool() const noexcept;
157
161 void
163
165 T*
166 get() const;
167
169 std::size_t
170 use_count() const;
171
172 template <class TT, class... Args>
173 friend SharedIntrusive<TT>
174 make_SharedIntrusive(Args&&... args);
175
176 template <class TT>
177 friend class SharedIntrusive;
178
179 template <class TT>
180 friend class SharedWeakUnion;
181
182 template <class TT>
183 friend class WeakIntrusive;
184
185private:
187 T*
189
194 void
196
200 void
202
208 T*
210
212 T* ptr_{nullptr};
213};
214
215//------------------------------------------------------------------------------
216
223template <class T>
225{
226public:
227 WeakIntrusive() = default;
228
230
232
234
235 // There is no move constructor from a strong intrusive ptr because
236 // moving would be move expensive than copying in this case (the strong
237 // ref would need to be decremented)
238 WeakIntrusive(SharedIntrusive<T> const&& rhs) = delete;
239
240 // Since there are no current use cases for copy assignment in
241 // WeakIntrusive, we delete this operator to simplify the implementation. If
242 // a need arises in the future, we can reintroduce it with proper
243 // consideration."
245 operator=(WeakIntrusive const&) = delete;
246
247 template <class TT>
251
253 void
254 adopt(T* ptr);
255
257
263 lock() const;
264
266 bool
267 expired() const;
268
273 void
275
276private:
277 T* ptr_ = nullptr;
278
284 void
286};
287
288//------------------------------------------------------------------------------
289
301template <class T>
303{
304 // Tagged pointer. Low bit determines if this is a strong or a weak
305 // pointer. The low bit must be masked to zero when converting back to a
306 // pointer. If the low bit is '1', this is a weak pointer.
307 static_assert(
308 alignof(T) >= 2,
309 "Bad alignment: Combo pointer requires low bit to be zero");
310
311public:
312 SharedWeakUnion() = default;
313
315
316 template <class TT>
319
321
322 template <class TT>
325
328
329 template <class TT>
333
334 template <class TT>
338
340
346 getStrong() const;
347
351 explicit
352 operator bool() const noexcept;
353
357 void
359
363 T*
364 get() const;
365
369 std::size_t
370 use_count() const;
371
373 bool
374 expired() const;
375
380 lock() const;
381
383 bool
384 isStrong() const;
385
387 bool
388 isWeak() const;
389
396 bool
398
404 bool
406
407private:
408 // Tagged pointer. Low bit determines if this is a strong or a weak
409 // pointer. The low bit must be masked to zero when converting back to a
410 // pointer. If the low bit is '1', this is a weak pointer.
411 std::uintptr_t tp_{0};
412 static constexpr std::uintptr_t tagMask = 1;
413 static constexpr std::uintptr_t ptrMask = ~tagMask;
414
415private:
418 T*
420
421 enum class RefStrength { strong, weak };
424 void
426
430
434 void
436};
437
438//------------------------------------------------------------------------------
439
446template <class TT, class... Args>
448make_SharedIntrusive(Args&&... args)
449{
450 auto p = new TT(std::forward<Args>(args)...);
451
452 static_assert(
453 noexcept(SharedIntrusive<TT>(
456 "SharedIntrusive constructor should not throw or this can leak "
457 "memory");
458
460}
461
462//------------------------------------------------------------------------------
463
464namespace intr_ptr {
465template <class T>
467
468template <class T>
470
471template <class T>
473
474template <class T, class... A>
476make_shared(A&&... args)
477{
478 return make_SharedIntrusive<T>(std::forward<A>(args)...);
479}
480
481template <class T, class TT>
482SharedPtr<T>
484{
486}
487
488template <class T, class TT>
489SharedPtr<T>
491{
493}
494} // namespace intr_ptr
495} // namespace ripple
496#endif
A shared intrusive pointer class that supports weak pointers.
bool operator!=(std::nullptr_t) const
T * ptr_
pointer to the type with an intrusive count
T & operator*() const noexcept
SharedIntrusive & operator=(SharedIntrusive const &rhs)
void adopt(T *p)
Adopt the raw pointer.
SharedIntrusive(T *p, TAdoptTag) noexcept
SharedIntrusive(SharedIntrusive< TT > &&rhs)
std::size_t use_count() const
Return the strong count.
SharedIntrusive & operator=(SharedIntrusive< TT > &&rhs)
T * unsafeGetRawPtr() const
Return the raw pointer held by this object.
friend SharedIntrusive< TT > make_SharedIntrusive(Args &&... args)
Create a shared intrusive pointer.
SharedIntrusive & operator=(SharedIntrusive &&rhs)
SharedIntrusive(SharedIntrusive &&rhs)
SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive< TT > &&rhs)
Create a new SharedIntrusive by dynamically casting the pointer controlled by the rhs param.
SharedIntrusive & operator=(SharedIntrusive< TT > const &rhs)
T * get() const
Get the raw pointer.
SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive< TT > &&rhs)
Create a new SharedIntrusive by statically casting the pointer controlled by the rhs param.
SharedIntrusive(SharedIntrusive const &rhs)
void reset()
Set the pointer to null, decrement the strong count, and run the appropriate release action.
SharedIntrusive(SharedIntrusive< TT > const &rhs)
void unsafeSetRawPtr(T *p)
Set the raw pointer directly.
SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive< TT > const &rhs)
Create a new SharedIntrusive by dynamically casting the pointer controlled by the rhs param.
SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive< TT > const &rhs)
Create a new SharedIntrusive by statically casting the pointer controlled by the rhs param.
void unsafeReleaseAndStore(T *next)
Exchange the current raw pointer held by this object with the given pointer.
T * unsafeExchange(T *p)
Exchange the raw pointer directly.
bool operator==(std::nullptr_t) const
A combination of a strong and a weak intrusive pointer stored in the space of a single pointer.
SharedIntrusive< T > getStrong() const
Return a strong pointer if this is already a strong pointer (i.e.
SharedIntrusive< T > lock() const
If this is a strong pointer, return the strong pointer.
T * unsafeGetRawPtr() const
Return the raw pointer held by this object.
bool expired() const
Return true if there is a non-zero strong count.
SharedWeakUnion & operator=(SharedIntrusive< TT > const &rhs)
bool isStrong() const
Return true is this represents a strong pointer.
SharedWeakUnion(SharedWeakUnion &&rhs)
SharedWeakUnion & operator=(SharedIntrusive< TT > &&rhs)
SharedWeakUnion(SharedIntrusive< TT > &&rhs)
bool convertToWeak()
If this is a strong pointer, attempt to convert it to a weak pointer.
T * get() const
If this is a strong pointer, return the raw pointer.
void reset()
Set the pointer to null, decrement the appropriate ref count, and run the appropriate release action.
std::size_t use_count() const
If this is a strong pointer, return the strong count.
SharedWeakUnion & operator=(SharedWeakUnion const &rhs)
SharedWeakUnion(SharedIntrusive< TT > const &rhs)
static constexpr std::uintptr_t ptrMask
bool convertToStrong()
If this is a weak pointer, attempt to convert it to a strong pointer.
void unsafeReleaseNoStore()
Decrement the appropriate ref count, and run the appropriate release action.
void unsafeSetRawPtr(T *p, RefStrength rs)
Set the raw pointer and tag bit directly.
bool isWeak() const
Return true is this represents a weak pointer.
void unsafeSetRawPtr(std::nullptr_t)
Set the raw pointer and tag bit to all zeros (strong null pointer).
static constexpr std::uintptr_t tagMask
SharedWeakUnion(SharedWeakUnion const &rhs)
A weak intrusive pointer class for the SharedIntrusive pointer class.
WeakIntrusive(SharedIntrusive< T > const &&rhs)=delete
bool expired() const
Return true if the strong count is zero.
WeakIntrusive & operator=(SharedIntrusive< TT > const &rhs)
void adopt(T *ptr)
Adopt the raw pointer and increment the weak count.
WeakIntrusive(SharedIntrusive< T > const &rhs)
void unsafeReleaseNoStore()
Decrement the weak count.
WeakIntrusive & operator=(WeakIntrusive const &)=delete
SharedIntrusive< T > lock() const
Get a strong pointer from the weak pointer, if possible.
WeakIntrusive(WeakIntrusive &&rhs)
void reset()
Set the pointer to null and decrement the weak count.
WeakIntrusive(WeakIntrusive const &rhs)
T is_same_v
SharedPtr< T > make_shared(A &&... args)
SharedPtr< T > static_pointer_cast(TT const &v)
SharedPtr< T > dynamic_pointer_cast(TT const &v)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
SharedIntrusive< TT > make_SharedIntrusive(Args &&... args)
Create a shared intrusive pointer.
STL namespace.
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.