rippled
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>
47concept CAdoptTag =
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.
82
84
85 template <class TT>
88
91
92 bool
94
95 bool
97
98 template <class TT>
102
105
106 template <class TT>
110
114 template <CAdoptTag TAdoptTag = SharedIntrusiveAdoptIncrementStrongTag>
115 void
116 adopt(T* p);
117
119
123 template <class TT>
125
129 template <class TT>
131
135 template <class TT>
137
141 template <class TT>
143
144 T&
145 operator*() const noexcept;
146
147 T*
148 operator->() const noexcept;
149
150 explicit
151 operator bool() const noexcept;
152
156 void
158
160 T*
161 get() const;
162
164 std::size_t
165 use_count() const;
166
167 template <class TT, class... Args>
168 friend SharedIntrusive<TT>
169 make_SharedIntrusive(Args&&... args);
170
171 template <class TT>
172 friend class SharedIntrusive;
173
174 template <class TT>
175 friend class SharedWeakUnion;
176
177 template <class TT>
178 friend class WeakIntrusive;
179
180private:
182 T*
184
189 void
191
195 void
197
203 T*
205
207 T* ptr_{nullptr};
208};
209
210//------------------------------------------------------------------------------
211
218template <class T>
220{
221public:
222 WeakIntrusive() = default;
223
225
227
229
230 // There is no move constructor from a strong intrusive ptr because
231 // moving would be move expensive than copying in this case (the strong
232 // ref would need to be decremented)
233 WeakIntrusive(SharedIntrusive<T> const&& rhs) = delete;
234
235 // Since there are no current use cases for copy assignment in
236 // WeakIntrusive, we delete this operator to simplify the implementation. If
237 // a need arises in the future, we can reintroduce it with proper
238 // consideration."
240 operator=(WeakIntrusive const&) = delete;
241
242 template <class TT>
246
248 void
249 adopt(T* ptr);
250
252
258 lock() const;
259
261 bool
262 expired() const;
263
268 void
270
271private:
272 T* ptr_ = nullptr;
273
279 void
281};
282
283//------------------------------------------------------------------------------
284
296template <class T>
298{
299 // Tagged pointer. Low bit determines if this is a strong or a weak
300 // pointer. The low bit must be masked to zero when converting back to a
301 // pointer. If the low bit is '1', this is a weak pointer.
302 static_assert(alignof(T) >= 2, "Bad alignment: Combo pointer requires low bit to be zero");
303
304public:
305 SharedWeakUnion() = default;
306
308
309 template <class TT>
312
314
315 template <class TT>
318
321
322 template <class TT>
326
327 template <class TT>
331
333
339 getStrong() const;
340
344 explicit
345 operator bool() const noexcept;
346
350 void
352
356 T*
357 get() const;
358
362 std::size_t
363 use_count() const;
364
366 bool
367 expired() const;
368
373 lock() const;
374
376 bool
377 isStrong() const;
378
380 bool
381 isWeak() const;
382
389 bool
391
397 bool
399
400private:
401 // Tagged pointer. Low bit determines if this is a strong or a weak
402 // pointer. The low bit must be masked to zero when converting back to a
403 // pointer. If the low bit is '1', this is a weak pointer.
404 std::uintptr_t tp_{0};
405 static constexpr std::uintptr_t tagMask = 1;
406 static constexpr std::uintptr_t ptrMask = ~tagMask;
407
408private:
411 T*
413
414 enum class RefStrength { strong, weak };
417 void
419
423
427 void
429};
430
431//------------------------------------------------------------------------------
432
439template <class TT, class... Args>
441make_SharedIntrusive(Args&&... args)
442{
443 auto p = new TT(std::forward<Args>(args)...);
444
445 static_assert(
447 "SharedIntrusive constructor should not throw or this can leak "
448 "memory");
449
451}
452
453//------------------------------------------------------------------------------
454
455namespace intr_ptr {
456template <class T>
458
459template <class T>
461
462template <class T>
464
465template <class T, class... A>
467make_shared(A&&... args)
468{
469 return make_SharedIntrusive<T>(std::forward<A>(args)...);
470}
471
472template <class T, class TT>
473SharedPtr<T>
475{
477}
478
479template <class T, class TT>
480SharedPtr<T>
482{
484}
485} // namespace intr_ptr
486} // 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.
T * unsafeGetRawPtr() const
Return the raw pointer held by this object.
SharedIntrusive(SharedIntrusive< TT > &&rhs)
T * get() const
Get the raw pointer.
void reset()
Set the pointer to null, decrement the strong count, and run the appropriate release action.
bool operator==(std::nullptr_t) const
SharedIntrusive & operator=(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(T *p)
Set the raw pointer directly.
SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive< TT > &&rhs)
Create a new SharedIntrusive by dynamically casting the pointer controlled by the rhs param.
T * unsafeExchange(T *p)
Exchange the raw pointer directly.
friend SharedIntrusive< TT > make_SharedIntrusive(Args &&... args)
Create a shared intrusive pointer.
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(T *next)
Exchange the current raw pointer held by this object with the given pointer.
SharedIntrusive(SharedIntrusive const &rhs)
SharedIntrusive(T *p, TAdoptTag) noexcept
bool operator!=(std::nullptr_t) const
SharedIntrusive & operator=(SharedIntrusive const &rhs)
T * ptr_
pointer to the type with an intrusive count
T & operator*() const noexcept
SharedIntrusive & operator=(SharedIntrusive< TT > &&rhs)
std::size_t use_count() const
Return the strong count.
SharedIntrusive(SharedIntrusive &&rhs)
SharedIntrusive(SharedIntrusive< TT > const &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(SharedWeakUnion const &rhs)
bool expired() const
Return true if there is a non-zero strong count.
SharedWeakUnion(SharedWeakUnion &&rhs)
void reset()
Set the pointer to null, 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.
T * unsafeGetRawPtr() const
Return the raw pointer held by this object.
SharedWeakUnion(SharedIntrusive< TT > &&rhs)
T * get() const
If this is a strong pointer, return the raw pointer.
static constexpr std::uintptr_t ptrMask
std::size_t use_count() const
If this is a strong pointer, return the strong count.
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(SharedIntrusive< TT > const &rhs)
SharedWeakUnion & operator=(SharedIntrusive< TT > const &rhs)
SharedWeakUnion & operator=(SharedWeakUnion const &rhs)
void unsafeReleaseNoStore()
Decrement the appropriate ref count, and run the appropriate release action.
SharedWeakUnion & operator=(SharedIntrusive< TT > &&rhs)
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.
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.
static constexpr std::uintptr_t tagMask
A weak intrusive pointer class for the SharedIntrusive pointer class.
WeakIntrusive(SharedIntrusive< T > const &&rhs)=delete
WeakIntrusive & operator=(SharedIntrusive< TT > const &rhs)
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=(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 is_same_v
STL namespace.
SharedPtr< T > static_pointer_cast(TT const &v)
SharedPtr< T > make_shared(A &&... args)
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:5
SharedIntrusive< TT > make_SharedIntrusive(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.