Ultralight  1.0.0
A fast, lightweight, HTML UI engine for native apps.
RefPtr.h
Go to the documentation of this file.
1 /*
15 * Portions of the below code are derived from 'RefPtr.h' from Apple's WTF,
16 * with the following license header:
17 *
18 * Copyright (C) 2013-2014 Apple Inc. All rights reserved.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 *
29 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
30 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
31 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
33 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
39 * THE POSSIBILITY OF SUCH DAMAGE.
40 */
41 
42 #pragma once
43 #include <Ultralight/Defines.h>
44 #include <assert.h>
45 #include <utility>
46 
47 namespace ultralight {
48 
53 class UExport RefCounted {
54  public:
55  virtual void AddRef() const = 0;
56  virtual void Release() const = 0;
57  virtual int ref_count() const = 0;
58  protected:
59  virtual ~RefCounted();
60 };
61 
62 inline void adopted(const void*) { }
63 
64 template<typename T> class Ref;
65 
75 template<typename T> Ref<T> AdoptRef(T&);
76 
83 template<typename T> class Ref {
84 public:
88  ~Ref()
89  {
90  if (instance_)
91  instance_->Release();
92  }
93 
97  Ref(T& object)
98  : instance_(&object)
99  {
100  instance_->AddRef();
101  }
102 
106  Ref(const Ref& other)
107  : instance_(other.instance_)
108  {
109  instance_->AddRef();
110  }
111 
115  template<typename U>
116  Ref(Ref<U>& other)
117  : instance_(other.ptr())
118  {
119  instance_->AddRef();
120  }
121 
125  template<typename U>
126  Ref(const Ref<U>& other)
127  : instance_(other.ptr())
128  {
129  instance_->AddRef();
130  }
131 
135  Ref(Ref&& other)
136  : instance_(&other.LeakRef())
137  {
138  assert(instance_);
139  }
140 
144  template<typename U>
145  Ref(Ref<U>&& other)
146  : instance_(&other.LeakRef())
147  {
148  assert(instance_);
149  }
150 
151  Ref& operator=(T& object)
152  {
153  assert(instance_);
154  object.AddRef();
155  instance_->Release();
156  instance_ = &object;
157  assert(instance_);
158  return *this;
159  }
160 
161  Ref& operator=(const Ref& other)
162  {
163  assert(instance_);
164  other.instance_->AddRef();
165  instance_->Release();
166  instance_ = other.instance_;
167  assert(instance_);
168  return *this;
169  }
170 
171  template<typename U>
172  Ref& operator=(const Ref<U>& other)
173  {
174  assert(instance_);
175  other.instance_->AddRef();
176  instance_->Release();
177  instance_ = other.instance_;
178  assert(instance_);
179  return *this;
180  }
181 
182  Ref& operator=(Ref&& reference)
183  {
184  assert(instance_);
185  instance_->Release();
186  instance_ = &reference.LeakRef();
187  assert(instance_);
188  return *this;
189  }
190 
191  template<typename U> Ref& operator=(Ref<U>&& reference)
192  {
193  assert(instance_);
194  instance_->Release();
195  instance_ = &reference.LeakRef();
196  assert(instance_);
197  return *this;
198  }
199 
200  const T* operator->() const { assert(instance_); return instance_; }
201  T* operator->() { assert(instance_); return instance_; }
202 
206  const T* ptr() const { assert(instance_); return instance_; }
207 
211  T* ptr() { assert(instance_); return instance_; }
212 
216  const T& get() const { assert(instance_); return *instance_; }
217 
221  T& get() { assert(instance_); return *instance_; }
222 
223  operator T&() { assert(instance_); return *instance_; }
224  operator const T&() const { assert(instance_); return *instance_; }
225 
226  template<typename U> Ref<T> Replace(Ref<U>&&);
227 
228  T& LeakRef() {
229  assert(instance_);
230 
231  T* result = std::move(instance_);
232  instance_ = std::forward<T*>(nullptr);
233  return *result;
234  }
235 
236  friend inline bool operator==(const Ref& a, const Ref& b) {
237  return a.instance_ == b.instance_;
238  }
239 
240  friend inline bool operator!=(const Ref& a, const Ref& b) {
241  return a.instance_ != b.instance_;
242  }
243 
244  friend inline bool operator<(const Ref& a, const Ref& b) {
245  return a.instance_ < b.instance_;
246  }
247 
248 protected:
249  friend Ref AdoptRef<T>(T&);
250  template<typename U> friend class RefPtr;
251 
252  enum AdoptTag { Adopt };
253  Ref(T& object, AdoptTag)
254  : instance_(&object)
255  {
256  }
257 
258  T* instance_;
259 };
260 
261 template<typename T> template<typename U> Ref<T> Ref<T>::Replace(Ref<U>&& reference)
262 {
263  auto oldReference = AdoptRef(*instance_);
264  instance_ = &reference.LeakRef();
265  return oldReference;
266 }
267 
268 template<typename T>
269 Ref<T> AdoptRef(T& reference)
270 {
271  adopted(&reference);
272  return Ref<T>(reference, Ref<T>::Adopt);
273 }
274 
281 template<typename T> class RefPtr {
282  public:
287  : instance_(nullptr)
288  {
289  }
290 
294  RefPtr(std::nullptr_t)
295  : instance_(nullptr)
296  {
297  }
298 
302  RefPtr(T* other)
303  : instance_(other)
304  {
305  if (instance_)
306  instance_->AddRef();
307  }
308 
312  RefPtr(const RefPtr& other)
313  : instance_(other.instance_)
314  {
315  if (instance_)
316  instance_->AddRef();
317  }
318 
322  template<typename U>
323  RefPtr(const RefPtr<U>& other)
324  : instance_(other.instance_)
325  {
326  if (instance_)
327  instance_->AddRef();
328  }
329 
333  RefPtr(RefPtr&& other)
334  : instance_(other.LeakRef())
335  {
336  }
337 
341  template<typename U>
342  RefPtr(RefPtr<U>&& other)
343  : instance_(other.LeakRef())
344  {
345  }
346 
350  template<typename U>
351  RefPtr(const Ref<U>& other)
352  : instance_(other.instance_)
353  {
354  if (instance_)
355  instance_->AddRef();
356  }
357 
361  template<typename U>
362  RefPtr(Ref<U>&& other);
363 
368  {
369  T* old_value = std::move(instance_);
370  instance_ = std::forward<T*>(nullptr);
371  if (old_value)
372  old_value->Release();
373  }
374 
378  T* get() const { return instance_; }
379 
380  T* LeakRef() {
381  T* result = std::move(instance_);
382  instance_ = std::forward<T*>(nullptr);
383  return result;
384  }
385 
386  T& operator*() const { assert(instance_); return *instance_; }
387  T* operator->() const { return instance_; }
388 
389  bool operator!() const { return !instance_; }
390 
391  // This conversion operator allows implicit conversion to bool but not to other integer types.
392  typedef T* (RefPtr::*UnspecifiedBoolType);
393  operator UnspecifiedBoolType() const { return instance_ ? &RefPtr::instance_ : nullptr; }
394 
395  RefPtr& operator=(const RefPtr&);
396  RefPtr& operator=(T*);
397  RefPtr& operator=(std::nullptr_t);
398  template<typename U> RefPtr& operator=(const RefPtr<U>&);
399  RefPtr& operator=(RefPtr&&);
400  template<typename U> RefPtr& operator=(RefPtr<U>&&);
401  template<typename U> RefPtr& operator=(Ref<U>&&);
402 
403  friend inline bool operator==(const RefPtr& a, const RefPtr& b) {
404  return a.instance_ == b.instance_;
405  }
406 
407  friend inline bool operator!=(const RefPtr& a, const RefPtr& b) {
408  return a.instance_ != b.instance_;
409  }
410 
411  friend inline bool operator<(const RefPtr& a, const RefPtr& b) {
412  return a.instance_ < b.instance_;
413  }
414 
415  void Swap(RefPtr&);
416 
417 private:
418  T* instance_;
419 };
420 
421 template<typename T>
422 template<typename U>
424  : instance_(&reference.LeakRef())
425 {
426 }
427 
428 template<typename T>
430 {
431  RefPtr ptr = other;
432  Swap(ptr);
433  return *this;
434 }
435 
436 template<typename T>
437 template<typename U>
438 RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& other)
439 {
440  RefPtr ptr = other;
441  Swap(ptr);
442  return *this;
443 }
444 
445 template<typename T>
446 RefPtr<T>& RefPtr<T>::operator=(T* object)
447 {
448  RefPtr ptr = object;
449  Swap(ptr);
450  return *this;
451 }
452 
453 template<typename T>
454 RefPtr<T>& RefPtr<T>::operator=(std::nullptr_t)
455 {
456  T* old_instance = std::move(instance_);
457  instance_ = std::forward<T*>(nullptr);
458  if (old_instance)
459  old_instance->Release();
460  return *this;
461 }
462 
463 template<typename T>
464 RefPtr<T>& RefPtr<T>::operator=(RefPtr&& other)
465 {
466  RefPtr ptr = std::move(other);
467  Swap(ptr);
468  return *this;
469 }
470 
471 template<typename T>
472 template<typename U>
473 RefPtr<T>& RefPtr<T>::operator=(RefPtr<U>&& other)
474 {
475  RefPtr ptr = std::move(other);
476  Swap(ptr);
477  return *this;
478 }
479 
480 template<typename T>
481 template<typename U>
482 RefPtr<T>& RefPtr<T>::operator=(Ref<U>&& other)
483 {
484  RefPtr ptr = std::move(other);
485  Swap(ptr);
486  return *this;
487 }
488 
489 template<typename T>
490 void RefPtr<T>::Swap(RefPtr& other)
491 {
492  std::swap(instance_, other.instance_);
493 }
494 
495 template<class T>
496 void Swap(RefPtr<T>& a, RefPtr<T>& b)
497 {
498  a.Swap(b);
499 }
500 
501 template<typename T, typename U>
502 bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
503 {
504  return a.get() == b.get();
505 }
506 
507 template<typename T, typename U>
508 bool operator==(const RefPtr<T>& a, U* b)
509 {
510  return a.get() == b;
511 }
512 
513 template<typename T, typename U>
514 bool operator==(T* a, const RefPtr<U>& b)
515 {
516  return a == b.get();
517 }
518 
519 template<typename T, typename U>
520 bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
521 {
522  return a.get() != b.get();
523 }
524 
525 template<typename T, typename U>
526 bool operator!=(const RefPtr<T>& a, U* b)
527 {
528  return a.get() != b;
529 }
530 
531 template<typename T, typename U>
532 bool operator!=(T* a, const RefPtr<U>& b)
533 {
534  return a != b.get();
535 }
536 
537 } // namespace ultralight
RefPtr(const Ref< U > &other)
Construct from a Ref.
Definition: RefPtr.h:351
Ref(Ref< U > &other)
Copy constructor with internal type conversion.
Definition: RefPtr.h:116
RefPtr(std::nullptr_t)
Construct a NULL ref-pointer.
Definition: RefPtr.h:294
RefPtr(const RefPtr &other)
Copy constructor.
Definition: RefPtr.h:312
RefPtr(RefPtr &&other)
Move constructor.
Definition: RefPtr.h:333
A non-nullable smart pointer.
Definition: RefPtr.h:64
A nullable smart pointer.
Definition: RefPtr.h:281
This is a set of common JavaScriptCore Helper functions to simplify sample code.
Definition: App.h:19
~RefPtr()
Destroy RefPtr (wll decrement ref-count by one)
Definition: RefPtr.h:367
Interface for all ref-counted objects that will be managed using the Ref<> and RefPtr<> smart pointer...
Definition: RefPtr.h:53
RefPtr(RefPtr< U > &&other)
Move constructor.
Definition: RefPtr.h:342
~Ref()
Destroy Ref (wll decrement ref-count by one)
Definition: RefPtr.h:88
Ref(const Ref &other)
Copy constructor.
Definition: RefPtr.h:106
RefPtr(T *other)
Construct from a pointer.
Definition: RefPtr.h:302
const T * ptr() const
Get a pointer to wrapped object.
Definition: RefPtr.h:206
RefPtr()
Construct a NULL ref-pointer.
Definition: RefPtr.h:286
Ref< T > AdoptRef(T &)
Helper for wrapping new objects with the Ref smart pointer.
Definition: RefPtr.h:269
T * get() const
Get a pointer to wrapped object.
Definition: RefPtr.h:378
T & get()
Get a reference to wrapped object.
Definition: RefPtr.h:221
Ref(Ref< U > &&other)
Move constructor.
Definition: RefPtr.h:145
const T & get() const
Get a reference to wrapped object.
Definition: RefPtr.h:216
Ref(T &object)
Construct Ref from a reference.
Definition: RefPtr.h:97
Ref(const Ref< U > &other)
Copy constructor with internal type conversion.
Definition: RefPtr.h:126
RefPtr(const RefPtr< U > &other)
Copy constructor with internal type conversion.
Definition: RefPtr.h:323
Ref(Ref &&other)
Move constructor.
Definition: RefPtr.h:135
T * ptr()
Get a pointer to wrapped object.
Definition: RefPtr.h:211