docs
Loading...
Searching...
No Matches
RefPtr.h
Go to the documentation of this file.
1///
2/// Copyright (C) 2026 Ultralight, Inc. All rights reserved.
3/// A license is required for commercial use. https://ultralig.ht
4///
5/*
6* Portions of the below code are derived from 'RefPtr.h' and
7* 'ThreadSafeWeakPtr.h' from Apple's WTF, with the following license header:
8*
9* Copyright (C) 2013-2024 Apple Inc. All rights reserved.
10*
11* Redistribution and use in source and binary forms, with or without
12* modification, are permitted provided that the following conditions
13* are met:
14* 1. Redistributions of source code must retain the above copyright
15* notice, this list of conditions and the following disclaimer.
16* 2. Redistributions in binary form must reproduce the above copyright
17* notice, this list of conditions and the following disclaimer in the
18* documentation and/or other materials provided with the distribution.
19*
20* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
24* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30* THE POSSIBILITY OF SUCH DAMAGE.
31*/
32
33#pragma once
34#include <Ultralight/Defines.h>
35#include <Ultralight/Lock.h>
36#include <Ultralight/platform/Allocator.h>
37#include <assert.h>
38#include <type_traits>
39#include <utility>
40
41namespace ultralight {
42
43class WeakControlBlock;
44
45///
46/// @brief Interface for all ref-counted objects that will be managed using
47/// the RefPtr<> smart pointer.
48///
50 public:
51 /// Increment the reference count (thread-safe).
52 virtual void AddRef() const = 0;
53
54 /// Decrement the reference count (thread-safe). The object is destroyed when the count reaches
55 /// zero.
56 virtual void Release() const = 0;
57
58 /// Get the current reference count.
59 virtual int ref_count() const = 0;
60
61 ///
62 /// Get the control block used to track weak references to this object.
63 ///
64 /// @return Returns the control block, or nullptr if the concrete type does not support weak
65 /// references (only types derived from WeakRefCounted do).
66 ///
67 /// @note This is internal bookkeeping for WeakPtr; you should never need to call it directly.
68 ///
69 virtual WeakControlBlock* weak_control_block() const { return nullptr; }
70
71 protected:
72 virtual ~RefCounted();
73};
74
75///
76/// @brief Interface for ref-counted objects that can additionally be observed via the
77/// WeakPtr<> smart pointer.
78///
79/// Types deriving this interface support weak references: a WeakPtr can observe the object's
80/// lifetime without owning it. WeakPtr<T> requires T to derive WeakRefCounted; using it with a
81/// plain RefCounted type is a compile error.
82///
84 public:
85 /// Get the control block used to track weak references to this object (never nullptr).
86 virtual WeakControlBlock* weak_control_block() const override = 0;
87
88 protected:
89 virtual ~WeakRefCounted() = default;
90};
91
92template<typename T> class RefPtr;
93
94///
95/// @brief Helper for wrapping new objects with the RefPtr smart pointer.
96///
97/// All ref-counted object are created with an initial ref-count of '1'.
98/// The AdoptRef() helper returns a RefPtr<T> without calling AddRef().
99/// This is used for creating new objects, like so:
100///
101/// RefPtr<Object> ref = AdoptRef(*new ObjectImpl());
102///
103template<typename T>
104RefPtr<T> AdoptRef(T& reference)
105{
106 return RefPtr<T>(reference, RefPtr<T>::Adopt);
107}
108
109///
110/// @brief Construct a new object of type T and wrap it in a RefPtr.
111///
112/// Equivalent to `AdoptRef(*new T(args...))`.
113///
114template<typename T, typename... Args>
115RefPtr<T> MakeRefPtr(Args&&... args)
116{
117 return AdoptRef(*new T(std::forward<Args>(args)...));
118}
119
120///
121/// @brief A nullable smart pointer.
122///
123/// This smart pointer automatically manages the lifetime of a RefCounted
124/// object. The managed instance may be NULL.
125///
126template<typename T> class RefPtr {
127 // Cross-type friendship: lets `RefPtr<Base>(const RefPtr<Derived>&)`
128 // and the matching move constructor read the other instantiation's
129 // `instance_` pointer during upcasting conversions.
130 template <typename U> friend class RefPtr;
131 public:
132 ///
133 /// Construct a NULL ref-pointer.
134 ///
135 constexpr RefPtr()
136 : instance_(nullptr)
137 {
138 }
139
140 ///
141 /// Construct a NULL ref-pointer.
142 ///
143 inline RefPtr(std::nullptr_t)
144 : instance_(nullptr)
145 {
146 }
147
148 ///
149 /// Construct from a pointer. (Will increment ref-count by one)
150 ///
151 inline RefPtr(T* other)
152 : instance_(other)
153 {
154 if (instance_)
155 instance_->AddRef();
156 }
157
158 ///
159 /// Copy constructor.
160 ///
161 inline RefPtr(const RefPtr& other)
162 : instance_(other.instance_)
163 {
164 if (instance_)
165 instance_->AddRef();
166 }
167
168 ///
169 /// Copy constructor with internal type conversion.
170 ///
171 template<typename U>
172 RefPtr(const RefPtr<U>& other)
173 : instance_(other.instance_)
174 {
175 if (instance_)
176 instance_->AddRef();
177 }
178
179 ///
180 /// Move constructor.
181 ///
182 inline RefPtr(RefPtr&& other)
183 : instance_(other.LeakRef())
184 {
185 }
186
187 ///
188 /// Move constructor.
189 ///
190 template<typename U>
192 : instance_(other.LeakRef())
193 {
194 }
195
196 ///
197 /// Destroy RefPtr (will decrement ref-count by one)
198 ///
199 inline ~RefPtr()
200 {
201 T* old_value = std::move(instance_);
202 instance_ = std::forward<T*>(nullptr);
203 if (old_value)
204 old_value->Release();
205 }
206
207 ///
208 /// Get a pointer to wrapped object.
209 ///
210 inline T* get() const { return instance_; }
211
212 /// Release ownership and return the raw pointer without decrementing the reference count.
213 ///
214 /// @warning The caller is responsible for eventually calling Release() on the returned pointer
215 /// to avoid a memory leak, or passing it to AdoptRef().
216 ///
217 T* LeakRef() {
218 T* result = std::move(instance_);
219 instance_ = std::forward<T*>(nullptr);
220 return result;
221 }
222
223 T& operator*() const { assert(instance_); return *instance_; }
224 inline T* operator->() const { return instance_; }
225
226 bool operator!() const { return !instance_; }
227
228 ///
229 /// Whether this RefPtr holds a non-null object.
230 ///
231 explicit operator bool() const { return instance_ != nullptr; }
232
235 RefPtr& operator=(std::nullptr_t);
236 template<typename U> RefPtr& operator=(const RefPtr<U>&);
238 template<typename U> RefPtr& operator=(RefPtr<U>&&);
239
240 friend inline bool operator==(const RefPtr& a, const RefPtr& b) {
241 return a.instance_ == b.instance_;
242 }
243
244 friend inline bool operator!=(const RefPtr& a, const RefPtr& b) {
245 return a.instance_ != b.instance_;
246 }
247
248 friend inline bool operator<(const RefPtr& a, const RefPtr& b) {
249 return a.instance_ < b.instance_;
250 }
251
252 ///
253 /// Releases the ownership of the managed object, if any
254 ///
255 void reset();
256
257 ///
258 /// Replaces the managed object with another.
259 ///
260 void reset(T* obj);
261
262 ///
263 /// Exchanges the stored pointer values and the ownerships of *this and ptr.
264 /// Reference counts, if any, are not adjusted.
265 ///
266 void swap(RefPtr& ptr);
267
268protected:
269 friend RefPtr AdoptRef<T>(T&);
270
271 enum AdoptTag { Adopt };
272 RefPtr(T& object, AdoptTag) : instance_(&object) { }
273
274private:
275 T* instance_;
276};
277
278template<typename T>
280{
281 RefPtr ptr = other;
282 swap(ptr);
283 return *this;
284}
285
286template<typename T>
287template<typename U>
289{
290 RefPtr ptr = other;
291 swap(ptr);
292 return *this;
293}
294
295template<typename T>
297{
298 RefPtr ptr = object;
299 swap(ptr);
300 return *this;
301}
302
303template<typename T>
305{
306 T* old_instance = std::move(instance_);
307 instance_ = std::forward<T*>(nullptr);
308 if (old_instance)
309 old_instance->Release();
310 return *this;
311}
312
313template<typename T>
315{
316 RefPtr ptr = std::move(other);
317 swap(ptr);
318 return *this;
319}
320
321template<typename T>
322template<typename U>
324{
325 RefPtr ptr = std::move(other);
326 swap(ptr);
327 return *this;
328}
329
330template <typename T> void RefPtr<T>::reset() { *this = nullptr; }
331
332template <typename T> void RefPtr<T>::reset(T* obj) { *this = obj; }
333
334template<typename T>
336{
337 std::swap(instance_, other.instance_);
338}
339
340template<class T>
342{
343 a.swap(b);
344}
345
346template <class T> class RefCountedImpl;
347
348///
349/// @brief Internal bookkeeping object that tracks the liveness of a weakly-referenced object.
350///
351/// Allocated on demand the first time a weak reference to an object is created, and destroyed
352/// when the last weak reference and the object itself are gone. You should never use this type
353/// directly; use WeakPtr instead.
354///
355/// @note The layout of this class is part of the library's binary interface and does not
356/// change within a major version.
357///
358class WeakControlBlock {
359 public:
360 WeakControlBlock(const WeakControlBlock&) = delete;
361 WeakControlBlock& operator=(const WeakControlBlock&) = delete;
362
363 // Control blocks are created inside the library but may be released (and therefore freed)
364 // from code inlined into the embedder's binary, so allocation must go through the library's
365 // exported allocator pair regardless of which runtime the caller was built with.
366 static void* operator new(size_t size) {
367 void* p = ul_malloc(size);
368 assert(p && "WeakControlBlock: allocation failed");
369 return p;
370 }
371 static void operator delete(void* p) { ul_free(p); }
372
373 /// Increment the weak reference count and return this control block.
374 WeakControlBlock* WeakRef() {
375 LockHolder locker(lock_);
376 ++weak_ref_count_;
377 return this;
378 }
379
380 /// Decrement the weak reference count. Destroys the control block when both counts are zero.
381 void WeakDeref() {
382 bool should_delete_control_block = false;
383 {
384 LockHolder locker(lock_);
385 assert(weak_ref_count_);
386 if (!--weak_ref_count_ && !strong_ref_count_)
387 should_delete_control_block = true;
388 }
389 if (should_delete_control_block)
390 delete this;
391 }
392
393 /// Increment the strong reference count. Only valid while the object is alive.
394 void StrongRef() const {
395 LockHolder locker(lock_);
396 assert(object_);
397 ++strong_ref_count_;
398 }
399
400 /// Decrement the strong reference count, destroying the object when it reaches zero.
401 template <typename T>
402 void StrongDeref() const {
403 T* object;
404 {
405 LockHolder locker(lock_);
406 assert(object_);
407 if (UL_LIKELY(--strong_ref_count_ != 0))
408 return;
409 object = static_cast<T*>(object_);
410 object_ = nullptr;
411 // Take a temporary weak ref so this control block survives until the delete below
412 // returns: the object's destructor may itself drop weak references to this block.
413 ++weak_ref_count_;
414 }
415
416 // The object's destructor (arbitrary user code) must run outside the lock above.
417 // Destruction routes through RefCountedImpl<T>: it is the only class the object's
418 // (typically protected) destructor befriends.
419 RefCountedImpl<T>::DeleteObject(object);
420
421 bool has_other_weak_refs;
422 {
423 LockHolder locker(lock_);
424 has_other_weak_refs = --weak_ref_count_ != 0;
425 }
426 if (!has_other_weak_refs)
427 delete this;
428 }
429
430 ///
431 /// Atomically take a strong reference if the object is still alive.
432 ///
433 /// @param maybe_interior_pointer The typed pointer held by the caller. This (rather than
434 /// the stored object pointer) is what gets returned so that interior pointers from
435 /// multiple inheritance resolve to the correct subobject.
436 ///
437 /// @return Returns a strong reference to the object, or nullptr if it has been destroyed.
438 ///
439 template <typename U>
440 RefPtr<U> MakeStrongRefIfPossible(const U* maybe_interior_pointer) const {
441 LockHolder locker(lock_);
442 if (object_) {
443 // Constructing RefPtr<U>(ptr) would call AddRef -> StrongRef and self-deadlock on
444 // lock_; bump the count directly and adopt.
445 ++strong_ref_count_;
446 return AdoptRef(*const_cast<U*>(maybe_interior_pointer));
447 }
448 return nullptr;
449 }
450
451 ///
452 /// Whether the object has been destroyed.
453 ///
454 /// @warning Racy hint: the object may be destroyed by another thread immediately after this
455 /// returns false. Never gate a dereference on it; use MakeStrongRefIfPossible().
456 ///
457 bool expired() const {
458 LockHolder locker(lock_);
459 return !object_;
460 }
461
462 /// Get the current strong reference count.
463 int ref_count() const {
464 LockHolder locker(lock_);
465 return static_cast<int>(strong_ref_count_);
466 }
467
468 /// Get the current weak reference count.
469 int weak_ref_count() const {
470 LockHolder locker(lock_);
471 return static_cast<int>(weak_ref_count_);
472 }
473
474 private:
475 template <class T> friend class RefCountedImpl;
476
477 explicit WeakControlBlock(void* object) : object_(object) { }
478
479 // Called by the creating thread before the control block is published; no lock needed.
480 void set_strong_ref_count_during_init(uint32_t count) { strong_ref_count_ = count; }
481
482 mutable Lock lock_;
483 mutable uint32_t strong_ref_count_ = 1;
484 mutable uint32_t weak_ref_count_ = 0;
485 mutable void* object_;
486};
487
488///
489/// @brief A weak (non-owning) smart pointer that observes a WeakRefCounted object.
490///
491/// A WeakPtr does not keep its object alive. Use Lock() to atomically obtain a strong
492/// RefPtr to the object; the result is null if the object has already been destroyed.
493///
494/// ## Usage
495///
496/// ```
497/// RefPtr<Bitmap> bitmap = Bitmap::Create(100, 100, BitmapFormat::BGRA8_UNORM_SRGB);
498/// WeakPtr<Bitmap> weak(bitmap);
499///
500/// if (RefPtr<Bitmap> strong = weak.Lock()) {
501/// // The object is alive and stays alive while 'strong' is in scope.
502/// }
503/// ```
504///
505/// Thread-safe: WeakPtr instances can be created, copied, and destroyed on any thread,
506/// and Lock() is race-free against concurrent destruction of the object.
507///
508/// \parblock
509/// @note `T` must derive from WeakRefCounted; using WeakPtr with a plain RefCounted
510/// type is a compile error.
511/// \endparblock
512///
513/// \parblock
514/// @note Only construct a WeakPtr from a fully-constructed object: never from `this`
515/// inside a constructor.
516/// \endparblock
517///
518template<typename T> class WeakPtr {
519 static_assert(std::is_base_of<WeakRefCounted, T>::value,
520 "WeakPtr<T> requires T to derive from WeakRefCounted");
521 template <typename U> friend class WeakPtr;
522 public:
523 ///
524 /// Construct a null WeakPtr.
525 ///
526 constexpr WeakPtr() : instance_(nullptr), control_block_(nullptr) { }
527
528 ///
529 /// Construct a null WeakPtr.
530 ///
531 WeakPtr(std::nullptr_t) : instance_(nullptr), control_block_(nullptr) { }
532
533 ///
534 /// Construct a WeakPtr observing the object held by a RefPtr (may be null).
535 ///
536 template<typename U>
537 WeakPtr(const RefPtr<U>& strong)
538 : instance_(strong.get()),
539 control_block_(strong ? strong->weak_control_block() : nullptr)
540 {
541 if (control_block_)
542 control_block_->WeakRef();
543 }
544
545 ///
546 /// Construct a WeakPtr observing a raw pointer (may be null).
547 ///
548 /// The object must currently be alive: the caller (or another owner) must hold a
549 /// strong reference to it.
550 ///
551 template<typename U>
552 explicit WeakPtr(U* instance)
553 : instance_(instance),
554 control_block_(instance ? instance->weak_control_block() : nullptr)
555 {
556 if (control_block_)
557 control_block_->WeakRef();
558 }
559
560 ///
561 /// Copy constructor.
562 ///
563 WeakPtr(const WeakPtr& other)
564 : instance_(other.instance_),
565 control_block_(other.control_block_ ? other.control_block_->WeakRef() : nullptr)
566 {
567 }
568
569 ///
570 /// Move constructor.
571 ///
573 : instance_(other.instance_), control_block_(other.control_block_)
574 {
575 other.instance_ = nullptr;
576 other.control_block_ = nullptr;
577 }
578
580 {
581 if (control_block_)
582 control_block_->WeakDeref();
583 }
584
585 WeakPtr& operator=(const WeakPtr& other)
586 {
587 WeakPtr ptr = other;
588 swap(ptr);
589 return *this;
590 }
591
593 {
594 WeakPtr ptr = std::move(other);
595 swap(ptr);
596 return *this;
597 }
598
599 WeakPtr& operator=(std::nullptr_t)
600 {
601 Reset();
602 return *this;
603 }
604
605 template<typename U>
607 {
608 WeakPtr ptr = strong;
609 swap(ptr);
610 return *this;
611 }
612
613 ///
614 /// Atomically take a strong reference to the observed object.
615 ///
616 /// @return Returns a RefPtr keeping the object alive, or a null RefPtr if the object has
617 /// been destroyed (or this WeakPtr is null).
618 ///
620 {
621 return control_block_ ? control_block_->MakeStrongRefIfPossible(instance_)
622 : RefPtr<T>(nullptr);
623 }
624
625 ///
626 /// Whether the observed object has been destroyed (or this WeakPtr is null).
627 ///
628 /// @warning Racy hint only: the object may be destroyed by another thread
629 /// immediately after this returns false. Never gate a dereference on it;
630 /// use Lock() instead.
631 ///
632 bool Expired() const { return !control_block_ || control_block_->expired(); }
633
634 ///
635 /// Stop observing the object and become a null WeakPtr.
636 ///
637 void Reset()
638 {
639 if (control_block_)
640 control_block_->WeakDeref();
641 control_block_ = nullptr;
642 instance_ = nullptr;
643 }
644
645 ///
646 /// Exchanges the observed objects of *this and other.
647 ///
648 void swap(WeakPtr& other)
649 {
650 std::swap(instance_, other.instance_);
651 std::swap(control_block_, other.control_block_);
652 }
653
654 private:
655 // Two-member storage: the typed pointer (not the control block's most-derived object
656 // pointer) is what Lock() returns, so interior pointers from multiple inheritance
657 // resolve to the correct subobject.
658 T* instance_;
659 WeakControlBlock* control_block_;
660};
661
662template<class T>
664{
665 a.swap(b);
666}
667
668template<typename T, typename U>
669bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
670{
671 return a.get() == b.get();
672}
673
674template<typename T, typename U>
675bool operator==(const RefPtr<T>& a, const U* b)
676{
677 return a.get() == b;
678}
679
680template<typename T, typename U>
681bool operator==(const T* a, const RefPtr<U>& b)
682{
683 return a == b.get();
684}
685
686template<typename T, typename U>
687bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
688{
689 return a.get() != b.get();
690}
691
692template<typename T, typename U>
693bool operator!=(const RefPtr<T>& a, const U* b)
694{
695 return a.get() != b;
696}
697
698template<typename T, typename U>
699bool operator!=(const T* a, const RefPtr<U>& b)
700{
701 return a != b.get();
702}
703
704} // namespace ultralight
#define UExport
Definition Exports.h:22
#define UL_LIKELY(x)
Definition Defines.h:84
Interface for all ref-counted objects that will be managed using the RefPtr<> smart pointer.
Definition RefPtr.h:49
virtual void AddRef() const =0
Increment the reference count (thread-safe).
virtual int ref_count() const =0
Get the current reference count.
virtual WeakControlBlock * weak_control_block() const
Get the control block used to track weak references to this object.
Definition RefPtr.h:69
virtual void Release() const =0
Decrement the reference count (thread-safe).
A nullable smart pointer.
Definition RefPtr.h:126
void reset(T *obj)
Replaces the managed object with another.
Definition RefPtr.h:332
T & operator*() const
Definition RefPtr.h:223
friend class RefPtr
Definition RefPtr.h:130
constexpr RefPtr()
Construct a NULL ref-pointer.
Definition RefPtr.h:135
friend RefPtr AdoptRef(T &)
Helper for wrapping new objects with the RefPtr smart pointer.
Definition RefPtr.h:104
void swap(RefPtr &ptr)
Exchanges the stored pointer values and the ownerships of *this and ptr.
Definition RefPtr.h:335
friend bool operator==(const RefPtr &a, const RefPtr &b)
Definition RefPtr.h:240
RefPtr(T &object, AdoptTag)
Definition RefPtr.h:272
RefPtr(RefPtr &&other)
Move constructor.
Definition RefPtr.h:182
AdoptTag
Definition RefPtr.h:271
@ Adopt
Definition RefPtr.h:271
RefPtr & operator=(RefPtr< U > &&)
bool operator!() const
Definition RefPtr.h:226
RefPtr & operator=(const RefPtr &)
Definition RefPtr.h:279
friend bool operator!=(const RefPtr &a, const RefPtr &b)
Definition RefPtr.h:244
RefPtr(std::nullptr_t)
Construct a NULL ref-pointer.
Definition RefPtr.h:143
RefPtr & operator=(const RefPtr< U > &)
T * operator->() const
Definition RefPtr.h:224
RefPtr & operator=(T *)
Definition RefPtr.h:296
RefPtr(T *other)
Construct from a pointer.
Definition RefPtr.h:151
RefPtr & operator=(std::nullptr_t)
Definition RefPtr.h:304
RefPtr(const RefPtr &other)
Copy constructor.
Definition RefPtr.h:161
RefPtr(RefPtr< U > &&other)
Move constructor.
Definition RefPtr.h:191
LayoutNode * LeakRef()
Definition RefPtr.h:217
friend bool operator<(const RefPtr &a, const RefPtr &b)
Definition RefPtr.h:248
void reset()
Releases the ownership of the managed object, if any.
Definition RefPtr.h:330
~RefPtr()
Destroy RefPtr (will decrement ref-count by one).
Definition RefPtr.h:199
RefPtr & operator=(RefPtr &&)
Definition RefPtr.h:314
T * get() const
Get a pointer to wrapped object.
Definition RefPtr.h:210
RefPtr(const RefPtr< U > &other)
Copy constructor with internal type conversion.
Definition RefPtr.h:172
A weak (non-owning) smart pointer that observes a WeakRefCounted object.
Definition RefPtr.h:518
bool Expired() const
Whether the observed object has been destroyed (or this WeakPtr is null).
Definition RefPtr.h:632
~WeakPtr()
Definition RefPtr.h:579
WeakPtr & operator=(const RefPtr< U > &strong)
Definition RefPtr.h:606
RefPtr< T > Lock() const
Atomically take a strong reference to the observed object.
Definition RefPtr.h:619
WeakPtr(const WeakPtr &other)
Copy constructor.
Definition RefPtr.h:563
friend class WeakPtr
Definition RefPtr.h:521
WeakPtr(U *instance)
Construct a WeakPtr observing a raw pointer (may be null).
Definition RefPtr.h:552
void Reset()
Stop observing the object and become a null WeakPtr.
Definition RefPtr.h:637
WeakPtr(WeakPtr &&other)
Move constructor.
Definition RefPtr.h:572
WeakPtr(std::nullptr_t)
Construct a null WeakPtr.
Definition RefPtr.h:531
constexpr WeakPtr()
Construct a null WeakPtr.
Definition RefPtr.h:526
WeakPtr & operator=(std::nullptr_t)
Definition RefPtr.h:599
WeakPtr & operator=(WeakPtr &&other)
Definition RefPtr.h:592
WeakPtr & operator=(const WeakPtr &other)
Definition RefPtr.h:585
WeakPtr(const RefPtr< U > &strong)
Construct a WeakPtr observing the object held by a RefPtr (may be null).
Definition RefPtr.h:537
void swap(WeakPtr &other)
Exchanges the observed objects of *this and other.
Definition RefPtr.h:648
Interface for ref-counted objects that can additionally be observed via the WeakPtr<> smart pointer.
Definition RefPtr.h:83
virtual ~WeakRefCounted()=default
virtual WeakControlBlock * weak_control_block() const override=0
Get the control block used to track weak references to this object (never nullptr).
Root namespace for every public Ultralight type, function, and enumeration.
void swap(RefPtr< T > &a, RefPtr< T > &b)
Definition RefPtr.h:341
std::lock_guard< Lock > LockHolder
Definition Lock.h:84
RefPtr< T > AdoptRef(T &reference)
Helper for wrapping new objects with the RefPtr smart pointer.
Definition RefPtr.h:104
bool operator==(const Matrix &a, const Matrix &b)
bool operator!=(const Matrix &a, const Matrix &b)
RefPtr< T > MakeRefPtr(Args &&... args)
Construct a new object of type T and wrap it in a RefPtr.
Definition RefPtr.h:115