| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Provides a smart pointer class for intrusively reference-counted objects. | |
| 6 | |
| 7 #ifndef MOJO_EDK_SYSTEM_REF_PTR_H_ | |
| 8 #define MOJO_EDK_SYSTEM_REF_PTR_H_ | |
| 9 | |
| 10 #include <assert.h> | |
| 11 | |
| 12 #include <cstddef> | |
| 13 #include <utility> | |
| 14 | |
| 15 #include "mojo/edk/system/ref_ptr_internal.h" | |
| 16 #include "mojo/public/cpp/system/macros.h" | |
| 17 | |
| 18 namespace mojo { | |
| 19 namespace system { | |
| 20 | |
| 21 // A smart pointer class for intrusively reference-counted objects (e.g., those | |
| 22 // subclassing |RefCountedThreadSafe| -- see ref_counted.h). | |
| 23 // | |
| 24 // Such objects require *adoption* to obtain the first |RefPtr|, which is | |
| 25 // accomplished using |AdoptRef| (see below). (This is due to such objects being | |
| 26 // constructed with a reference count of 1. The adoption requirement is | |
| 27 // enforced, at least in Debug builds, by assertions.) | |
| 28 // | |
| 29 // E.g., if |Foo| is an intrusively reference-counted class: | |
| 30 // | |
| 31 // // The |AdoptRef| may be put in a static factory method (e.g., if |Foo|'s | |
| 32 // // constructor is private). | |
| 33 // RefPtr<Foo> my_foo_ptr(AdoptRef(new Foo())); | |
| 34 // | |
| 35 // // Now OK, since "my Foo" has been adopted ... | |
| 36 // RefPtr<Foo> another_ptr_to_my_foo(my_foo_ptr.get()); | |
| 37 // | |
| 38 // // ... though this would preferable in this situation. | |
| 39 // RefPtr<Foo> yet_another_ptr_to_my_foo(my_foo_ptr); | |
| 40 // | |
| 41 // Unlike Chromium's |scoped_refptr|, |RefPtr| is only explicitly constructible | |
| 42 // from a plain pointer (and not assignable). It is however implicitly | |
| 43 // constructible from |nullptr|. So: | |
| 44 // | |
| 45 // RefPtr<Foo> foo(plain_ptr_to_adopted_foo); // OK. | |
| 46 // foo = plain_ptr_to_adopted_foo; // Not OK (doesn't compile). | |
| 47 // foo = RefPtr<Foo>(plain_ptr_to_adopted_foo); // OK. | |
| 48 // foo = nullptr; // OK. | |
| 49 // | |
| 50 // And if we have |void MyFunction(RefPtr<Foo> foo)|, calling it using | |
| 51 // |MyFunction(nullptr)| is also valid. | |
| 52 // | |
| 53 // Implementation note: For copy/move constructors/operator=s, we often have | |
| 54 // templated versions, so that the operation can be done on a |RefPtr<U>|, where | |
| 55 // |U| is a subclass of |T|. However, we also have non-templated versions with | |
| 56 // |U = T|, since the templated versions don't count as copy/move | |
| 57 // constructors/operator=s for the purposes of causing the default copy | |
| 58 // constructor/operator= to be deleted. E.g., if we didn't declare any | |
| 59 // non-templated versions, we'd get the default copy constructor/operator= (we'd | |
| 60 // only not get the default move constructor/operator= by virtue of having a | |
| 61 // destructor)! (In fact, it'd suffice to only declare a non-templated move | |
| 62 // constructor or move operator=, which would cause the copy | |
| 63 // constructor/operator= to be deleted, but for clarity we include explicit | |
| 64 // non-templated versions of everything.) | |
| 65 template <typename T> | |
| 66 class RefPtr { | |
| 67 public: | |
| 68 RefPtr() : ptr_(nullptr) {} | |
| 69 RefPtr(std::nullptr_t) : ptr_(nullptr) {} | |
| 70 | |
| 71 // Explicit constructor from a plain pointer (to an object that must have | |
| 72 // already been adopted). (Note that in |T::T()|, references to |this| cannot | |
| 73 // be taken, since the object being constructed will not have been adopted | |
| 74 // yet.) | |
| 75 template <typename U> | |
| 76 explicit RefPtr(U* p) | |
| 77 : ptr_(p) { | |
| 78 if (ptr_) | |
| 79 ptr_->AddRef(); | |
| 80 } | |
| 81 | |
| 82 // Copy constructor. | |
| 83 RefPtr(const RefPtr<T>& r) : ptr_(r.ptr_) { | |
| 84 if (ptr_) | |
| 85 ptr_->AddRef(); | |
| 86 } | |
| 87 | |
| 88 template <typename U> | |
| 89 RefPtr(const RefPtr<U>& r) | |
| 90 : ptr_(r.ptr_) { | |
| 91 if (ptr_) | |
| 92 ptr_->AddRef(); | |
| 93 } | |
| 94 | |
| 95 // Move constructor. | |
| 96 RefPtr(RefPtr<T>&& r) : ptr_(r.ptr_) { r.ptr_ = nullptr; } | |
| 97 | |
| 98 template <typename U> | |
| 99 RefPtr(RefPtr<U>&& r) | |
| 100 : ptr_(r.ptr_) { | |
| 101 r.ptr_ = nullptr; | |
| 102 } | |
| 103 | |
| 104 // Destructor. | |
| 105 ~RefPtr() { | |
| 106 if (ptr_) | |
| 107 ptr_->Release(); | |
| 108 } | |
| 109 | |
| 110 T* get() const { return ptr_; } | |
| 111 | |
| 112 T& operator*() const { | |
| 113 assert(ptr_); | |
| 114 return *ptr_; | |
| 115 } | |
| 116 | |
| 117 T* operator->() const { | |
| 118 assert(ptr_); | |
| 119 return ptr_; | |
| 120 } | |
| 121 | |
| 122 // Copy assignment. | |
| 123 RefPtr<T>& operator=(const RefPtr<T>& r) { | |
| 124 // Call |AddRef()| first so self-assignments work. | |
| 125 if (r.ptr_) | |
| 126 r.ptr_->AddRef(); | |
| 127 T* old_ptr = ptr_; | |
| 128 ptr_ = r.ptr_; | |
| 129 if (old_ptr) | |
| 130 old_ptr->Release(); | |
| 131 return *this; | |
| 132 } | |
| 133 | |
| 134 template <typename U> | |
| 135 RefPtr<T>& operator=(const RefPtr<U>& r) { | |
| 136 // Call |AddRef()| first so self-assignments work. | |
| 137 if (r.ptr_) | |
| 138 r.ptr_->AddRef(); | |
| 139 T* old_ptr = ptr_; | |
| 140 ptr_ = r.ptr_; | |
| 141 if (old_ptr) | |
| 142 old_ptr->Release(); | |
| 143 return *this; | |
| 144 } | |
| 145 | |
| 146 // Move assignment. | |
| 147 // Note: Like |std::shared_ptr|, we support self-move and move assignment is | |
| 148 // equivalent to |RefPtr<T>(std::move(r)).swap(*this)|. | |
| 149 RefPtr<T>& operator=(RefPtr<T>&& r) { | |
| 150 RefPtr<T>(std::move(r)).swap(*this); | |
| 151 return *this; | |
| 152 } | |
| 153 | |
| 154 template <typename U> | |
| 155 RefPtr<T>& operator=(RefPtr<U>&& r) { | |
| 156 RefPtr<T>(std::move(r)).swap(*this); | |
| 157 return *this; | |
| 158 } | |
| 159 | |
| 160 void swap(RefPtr<T>& r) { | |
| 161 T* p = ptr_; | |
| 162 ptr_ = r.ptr_; | |
| 163 r.ptr_ = p; | |
| 164 } | |
| 165 | |
| 166 // Returns a new |RefPtr<T>| with the same contents as this pointer. Useful | |
| 167 // when a function takes a |RefPtr<T>&&| argument and the caller wants to | |
| 168 // retain its reference (rather than moving it). | |
| 169 RefPtr<T> Clone() const { return *this; } | |
| 170 | |
| 171 // For compatibility with base. | |
| 172 // TODO(vtl): Remove this when we can. | |
| 173 RefPtr<T>&& Pass() MOJO_WARN_UNUSED_RESULT { return std::move(*this); } | |
| 174 | |
| 175 explicit operator bool() const { return !!ptr_; } | |
| 176 | |
| 177 template <typename U> | |
| 178 bool operator==(const RefPtr<U>& rhs) const { | |
| 179 return ptr_ == rhs.ptr_; | |
| 180 } | |
| 181 | |
| 182 template <typename U> | |
| 183 bool operator!=(const RefPtr<U>& rhs) const { | |
| 184 return !operator==(rhs); | |
| 185 } | |
| 186 | |
| 187 template <typename U> | |
| 188 bool operator<(const RefPtr<U>& rhs) const { | |
| 189 return ptr_ < rhs.ptr_; | |
| 190 } | |
| 191 | |
| 192 private: | |
| 193 template <typename U> | |
| 194 friend class RefPtr; | |
| 195 | |
| 196 friend RefPtr<T> AdoptRef<T>(T*); | |
| 197 | |
| 198 enum AdoptTag { ADOPT }; | |
| 199 RefPtr(T* ptr, AdoptTag) : ptr_(ptr) { assert(ptr_); } | |
| 200 | |
| 201 T* ptr_; | |
| 202 }; | |
| 203 | |
| 204 // Adopts a newly-created |T|. Typically used in a static factory method, like: | |
| 205 // | |
| 206 // // static | |
| 207 // RefPtr<Foo> Foo::Create() { | |
| 208 // return AdoptRef(new Foo()); | |
| 209 // } | |
| 210 template <typename T> | |
| 211 inline RefPtr<T> AdoptRef(T* ptr) { | |
| 212 #ifndef NDEBUG | |
| 213 ptr->Adopt(); | |
| 214 #endif | |
| 215 return RefPtr<T>(ptr, RefPtr<T>::ADOPT); | |
| 216 } | |
| 217 | |
| 218 // Creates an intrusively reference counted |T|, producing a |RefPtr<T>| (and | |
| 219 // performing the required adoption). Use like: | |
| 220 // | |
| 221 // auto my_foo = MakeRefCounted<Foo>(ctor_arg1, ctor_arg2); | |
| 222 // | |
| 223 // (|my_foo| will be of type |RefPtr<Foo>|.) | |
| 224 template <typename T, typename... Args> | |
| 225 RefPtr<T> MakeRefCounted(Args&&... args) { | |
| 226 return internal::MakeRefCountedHelper<T>::MakeRefCounted( | |
| 227 std::forward<Args>(args)...); | |
| 228 } | |
| 229 | |
| 230 } // namespace system | |
| 231 } // namespace mojo | |
| 232 | |
| 233 #endif // MOJO_EDK_SYSTEM_REF_PTR_H_ | |
| OLD | NEW |