Loading...
Searching...
No Matches
RefPtr.h
Go to the documentation of this file.
1/**************************************************************************************************
2 * This file is a part of Ultralight. *
3 * *
4 * See <https://ultralig.ht> for licensing and more. *
5 * *
6 * (C) 2024 Ultralight, Inc. *
7 **************************************************************************************************/
8/*
9* Portions of the below code are derived from 'RefPtr.h' from Apple's WTF,
10* with the following license header:
11*
12* Copyright (C) 2013-2014 Apple Inc. All rights reserved.
13*
14* Redistribution and use in source and binary forms, with or without
15* modification, are permitted provided that the following conditions
16* are met:
17* 1. Redistributions of source code must retain the above copyright
18* notice, this list of conditions and the following disclaimer.
19* 2. Redistributions in binary form must reproduce the above copyright
20* notice, this list of conditions and the following disclaimer in the
21* documentation and/or other materials provided with the distribution.
22*
23* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
24* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
27* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33* THE POSSIBILITY OF SUCH DAMAGE.
34*/
35
36#pragma once
37#include <Ultralight/Defines.h>
38#include <assert.h>
39#include <utility>
40
41namespace ultralight {
42
43///
44/// @brief Interface for all ref-counted objects that will be managed using
45/// the RefPtr<> smart pointer.
46///
48 public:
49 virtual void AddRef() const = 0;
50 virtual void Release() const = 0;
51 virtual int ref_count() const = 0;
52 protected:
53 virtual ~RefCounted();
54};
55
56template<typename T> class RefPtr;
57
58///
59/// @brief Helper for wrapping new objects with the RefPtr smart pointer.
60///
61/// All ref-counted object are created with an initial ref-count of '1'.
62/// The AdoptRef() helper returns a RefPtr<T> without calling AddRef().
63/// This is used for creating new objects, like so:
64///
65/// RefPtr<Object> ref = AdoptRef(*new ObjectImpl());
66///
67template<typename T>
68RefPtr<T> AdoptRef(T& reference)
69{
70 return RefPtr<T>(reference, RefPtr<T>::Adopt);
71}
72
73///
74/// @brief A nullable smart pointer.
75///
76/// This smart pointer automatically manages the lifetime of a RefCounted
77/// object. The managed instance may be NULL.
78///
79template<typename T> class RefPtr {
80 public:
81 ///
82 /// Construct a NULL ref-pointer.
83 ///
84 constexpr RefPtr()
85 : instance_(nullptr)
86 {
87 }
88
89 ///
90 /// Construct a NULL ref-pointer.
91 ///
92 inline RefPtr(std::nullptr_t)
93 : instance_(nullptr)
94 {
95 }
96
97 ///
98 /// Construct from a pointer. (Will increment ref-count by one)
99 ///
100 inline RefPtr(T* other)
101 : instance_(other)
102 {
103 if (instance_)
104 instance_->AddRef();
105 }
106
107 ///
108 /// Copy constructor.
109 ///
110 inline RefPtr(const RefPtr& other)
111 : instance_(other.instance_)
112 {
113 if (instance_)
114 instance_->AddRef();
115 }
116
117 ///
118 /// Copy constructor with internal type conversion.
119 ///
120 template<typename U>
121 RefPtr(const RefPtr<U>& other)
122 : instance_(other.instance_)
123 {
124 if (instance_)
125 instance_->AddRef();
126 }
127
128 ///
129 /// Move constructor.
130 ///
131 inline RefPtr(RefPtr&& other)
132 : instance_(other.LeakRef())
133 {
134 }
135
136 ///
137 /// Move constructor.
138 ///
139 template<typename U>
141 : instance_(other.LeakRef())
142 {
143 }
144
145 ///
146 /// Destroy RefPtr (wll decrement ref-count by one)
147 ///
148 inline ~RefPtr()
149 {
150 T* old_value = std::move(instance_);
151 instance_ = std::forward<T*>(nullptr);
152 if (old_value)
153 old_value->Release();
154 }
155
156 ///
157 /// Get a pointer to wrapped object.
158 ///
159 inline T* get() const { return instance_; }
160
161 T* LeakRef() {
162 T* result = std::move(instance_);
163 instance_ = std::forward<T*>(nullptr);
164 return result;
165 }
166
167 T& operator*() const { assert(instance_); return *instance_; }
168 inline T* operator->() const { return instance_; }
169
170 bool operator!() const { return !instance_; }
171
172 // This conversion operator allows implicit conversion to bool but not to other integer types.
174 operator UnspecifiedBoolType() const { return instance_ ? &RefPtr::instance_ : nullptr; }
175
176 RefPtr& operator=(const RefPtr&);
177 RefPtr& operator=(T*);
178 RefPtr& operator=(std::nullptr_t);
179 template<typename U> RefPtr& operator=(const RefPtr<U>&);
181 template<typename U> RefPtr& operator=(RefPtr<U>&&);
182
183 friend inline bool operator==(const RefPtr& a, const RefPtr& b) {
184 return a.instance_ == b.instance_;
185 }
186
187 friend inline bool operator!=(const RefPtr& a, const RefPtr& b) {
188 return a.instance_ != b.instance_;
189 }
190
191 friend inline bool operator<(const RefPtr& a, const RefPtr& b) {
192 return a.instance_ < b.instance_;
193 }
194
195 ///
196 /// Releases the ownership of the managed object, if any
197 ///
198 void reset();
199
200 ///
201 /// Replaces the managed object with another.
202 ///
203 void reset(T* obj);
204
205 ///
206 /// Exchanges the stored pointer values and the ownerships of *this and ptr.
207 /// Reference counts, if any, are not adjusted.
208 ///
209 void swap(RefPtr& ptr);
210
211protected:
212 friend RefPtr AdoptRef<T>(T&);
213
214 enum AdoptTag { Adopt };
215 RefPtr(T& object, AdoptTag) : instance_(&object) { }
216
217private:
218 T* instance_;
219};
220
221template<typename T>
223{
224 RefPtr ptr = other;
225 swap(ptr);
226 return *this;
227}
228
229template<typename T>
230template<typename U>
232{
233 RefPtr ptr = other;
234 swap(ptr);
235 return *this;
236}
237
238template<typename T>
240{
241 RefPtr ptr = object;
242 swap(ptr);
243 return *this;
244}
245
246template<typename T>
248{
249 T* old_instance = std::move(instance_);
250 instance_ = std::forward<T*>(nullptr);
251 if (old_instance)
252 old_instance->Release();
253 return *this;
254}
255
256template<typename T>
258{
259 RefPtr ptr = std::move(other);
260 swap(ptr);
261 return *this;
262}
263
264template<typename T>
265template<typename U>
267{
268 RefPtr ptr = std::move(other);
269 swap(ptr);
270 return *this;
271}
272
273template <typename T> void RefPtr<T>::reset() { *this = nullptr; }
274
275template <typename T> void RefPtr<T>::reset(T* obj) { *this = obj; }
276
277template<typename T>
279{
280 std::swap(instance_, other.instance_);
281}
282
283template<class T>
285{
286 a.swap(b);
287}
288
289template<typename T, typename U>
290bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
291{
292 return a.get() == b.get();
293}
294
295template<typename T, typename U>
296bool operator==(const RefPtr<T>& a, const U* b)
297{
298 return a.get() == b;
299}
300
301template<typename T, typename U>
302bool operator==(const T* a, const RefPtr<U>& b)
303{
304 return a == b.get();
305}
306
307template<typename T, typename U>
308bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
309{
310 return a.get() != b.get();
311}
312
313template<typename T, typename U>
314bool operator!=(const RefPtr<T>& a, const U* b)
315{
316 return a.get() != b;
317}
318
319template<typename T, typename U>
320bool operator!=(const T* a, const RefPtr<U>& b)
321{
322 return a != b.get();
323}
324
325} // namespace ultralight
#define UExport
Definition Exports.h:25
Interface for all ref-counted objects that will be managed using the RefPtr<> smart pointer.
Definition RefPtr.h:47
virtual void AddRef() const =0
virtual int ref_count() const =0
virtual void Release() const =0
A nullable smart pointer.
Definition RefPtr.h:79
T & operator*() const
Definition RefPtr.h:167
constexpr RefPtr()
Construct a NULL ref-pointer.
Definition RefPtr.h:84
friend RefPtr AdoptRef(T &)
Helper for wrapping new objects with the RefPtr smart pointer.
Definition RefPtr.h:68
void swap(RefPtr &ptr)
Exchanges the stored pointer values and the ownerships of *this and ptr.
Definition RefPtr.h:278
friend bool operator==(const RefPtr &a, const RefPtr &b)
Definition RefPtr.h:183
RefPtr(T &object, AdoptTag)
Definition RefPtr.h:215
RefPtr(RefPtr &&other)
Move constructor.
Definition RefPtr.h:131
AdoptTag
Definition RefPtr.h:214
@ Adopt
Definition RefPtr.h:214
T *RefPtr::* UnspecifiedBoolType
Definition RefPtr.h:173
RefPtr & operator=(RefPtr< U > &&)
bool operator!() const
Definition RefPtr.h:170
RefPtr & operator=(const RefPtr &)
Definition RefPtr.h:222
friend bool operator!=(const RefPtr &a, const RefPtr &b)
Definition RefPtr.h:187
RefPtr(std::nullptr_t)
Construct a NULL ref-pointer.
Definition RefPtr.h:92
RefPtr & operator=(const RefPtr< U > &)
T * operator->() const
Definition RefPtr.h:168
RefPtr(T *other)
Construct from a pointer.
Definition RefPtr.h:100
RefPtr(const RefPtr &other)
Copy constructor.
Definition RefPtr.h:110
RefPtr(RefPtr< U > &&other)
Move constructor.
Definition RefPtr.h:140
T * LeakRef()
Definition RefPtr.h:161
friend bool operator<(const RefPtr &a, const RefPtr &b)
Definition RefPtr.h:191
void reset()
Releases the ownership of the managed object, if any.
Definition RefPtr.h:273
~RefPtr()
Destroy RefPtr (wll decrement ref-count by one)
Definition RefPtr.h:148
T * get() const
Get a pointer to wrapped object.
Definition RefPtr.h:159
RefPtr(const RefPtr< U > &other)
Copy constructor with internal type conversion.
Definition RefPtr.h:121
Definition App.h:14
void swap(RefPtr< T > &a, RefPtr< T > &b)
Definition RefPtr.h:284
RefPtr< T > AdoptRef(T &reference)
Helper for wrapping new objects with the RefPtr smart pointer.
Definition RefPtr.h:68
bool operator==(const Matrix &a, const Matrix &b)
bool operator!=(const Matrix &a, const Matrix &b)