1 /* 2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef RTC_BASE_WEAK_PTR_H_ 12 #define RTC_BASE_WEAK_PTR_H_ 13 14 #include <memory> 15 #include <utility> 16 17 #include "api/scoped_refptr.h" 18 #include "api/sequence_checker.h" 19 #include "rtc_base/ref_count.h" 20 #include "rtc_base/ref_counted_object.h" 21 #include "rtc_base/system/no_unique_address.h" 22 23 // The implementation is borrowed from chromium except that it does not 24 // implement SupportsWeakPtr. 25 26 // Weak pointers are pointers to an object that do not affect its lifetime, 27 // and which may be invalidated (i.e. reset to nullptr) by the object, or its 28 // owner, at any time, most commonly when the object is about to be deleted. 29 30 // Weak pointers are useful when an object needs to be accessed safely by one 31 // or more objects other than its owner, and those callers can cope with the 32 // object vanishing and e.g. tasks posted to it being silently dropped. 33 // Reference-counting such an object would complicate the ownership graph and 34 // make it harder to reason about the object's lifetime. 35 36 // EXAMPLE: 37 // 38 // class Controller { 39 // public: 40 // Controller() : weak_factory_(this) {} 41 // void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); } 42 // void WorkComplete(const Result& result) { ... } 43 // private: 44 // // Member variables should appear before the WeakPtrFactory, to ensure 45 // // that any WeakPtrs to Controller are invalidated before its members 46 // // variable's destructors are executed, rendering them invalid. 47 // WeakPtrFactory<Controller> weak_factory_; 48 // }; 49 // 50 // class Worker { 51 // public: 52 // static void StartNew(const WeakPtr<Controller>& controller) { 53 // Worker* worker = new Worker(controller); 54 // // Kick off asynchronous processing... 55 // } 56 // private: 57 // Worker(const WeakPtr<Controller>& controller) 58 // : controller_(controller) {} 59 // void DidCompleteAsynchronousProcessing(const Result& result) { 60 // if (controller_) 61 // controller_->WorkComplete(result); 62 // } 63 // WeakPtr<Controller> controller_; 64 // }; 65 // 66 // With this implementation a caller may use SpawnWorker() to dispatch multiple 67 // Workers and subsequently delete the Controller, without waiting for all 68 // Workers to have completed. 69 70 // ------------------------- IMPORTANT: Thread-safety ------------------------- 71 72 // Weak pointers may be passed safely between threads, but must always be 73 // dereferenced and invalidated on the same TaskQueue or thread, otherwise 74 // checking the pointer would be racey. 75 // 76 // To ensure correct use, the first time a WeakPtr issued by a WeakPtrFactory 77 // is dereferenced, the factory and its WeakPtrs become bound to the calling 78 // TaskQueue/thread, and cannot be dereferenced or 79 // invalidated on any other TaskQueue/thread. Bound WeakPtrs can still be handed 80 // off to other TaskQueues, e.g. to use to post tasks back to object on the 81 // bound sequence. 82 // 83 // Thus, at least one WeakPtr object must exist and have been dereferenced on 84 // the correct thread to enforce that other WeakPtr objects will enforce they 85 // are used on the desired thread. 86 87 namespace rtc { 88 89 namespace internal { 90 91 class WeakReference { 92 public: 93 // Although Flag is bound to a specific sequence, it may be 94 // deleted from another via base::WeakPtr::~WeakPtr(). 95 class Flag : public RefCountInterface { 96 public: 97 Flag(); 98 99 void Invalidate(); 100 bool IsValid() const; 101 102 private: 103 friend class RefCountedObject<Flag>; 104 105 ~Flag() override; 106 107 RTC_NO_UNIQUE_ADDRESS ::webrtc::SequenceChecker checker_; 108 bool is_valid_; 109 }; 110 111 WeakReference(); 112 explicit WeakReference(const Flag* flag); 113 ~WeakReference(); 114 115 WeakReference(WeakReference&& other); 116 WeakReference(const WeakReference& other); 117 WeakReference& operator=(WeakReference&& other) = default; 118 WeakReference& operator=(const WeakReference& other) = default; 119 120 bool is_valid() const; 121 122 private: 123 scoped_refptr<const Flag> flag_; 124 }; 125 126 class WeakReferenceOwner { 127 public: 128 WeakReferenceOwner(); 129 ~WeakReferenceOwner(); 130 131 WeakReference GetRef() const; 132 HasRefs()133 bool HasRefs() const { return flag_.get() && !flag_->HasOneRef(); } 134 135 void Invalidate(); 136 137 private: 138 mutable scoped_refptr<RefCountedObject<WeakReference::Flag>> flag_; 139 }; 140 141 // This class simplifies the implementation of WeakPtr's type conversion 142 // constructor by avoiding the need for a public accessor for ref_. A 143 // WeakPtr<T> cannot access the private members of WeakPtr<U>, so this 144 // base class gives us a way to access ref_ in a protected fashion. 145 class WeakPtrBase { 146 public: 147 WeakPtrBase(); 148 ~WeakPtrBase(); 149 150 WeakPtrBase(const WeakPtrBase& other) = default; 151 WeakPtrBase(WeakPtrBase&& other) = default; 152 WeakPtrBase& operator=(const WeakPtrBase& other) = default; 153 WeakPtrBase& operator=(WeakPtrBase&& other) = default; 154 155 protected: 156 explicit WeakPtrBase(const WeakReference& ref); 157 158 WeakReference ref_; 159 }; 160 161 } // namespace internal 162 163 template <typename T> 164 class WeakPtrFactory; 165 166 template <typename T> 167 class WeakPtr : public internal::WeakPtrBase { 168 public: WeakPtr()169 WeakPtr() : ptr_(nullptr) {} 170 171 // Allow conversion from U to T provided U "is a" T. Note that this 172 // is separate from the (implicit) copy and move constructors. 173 template <typename U> WeakPtr(const WeakPtr<U> & other)174 WeakPtr(const WeakPtr<U>& other) 175 : internal::WeakPtrBase(other), ptr_(other.ptr_) {} 176 template <typename U> WeakPtr(WeakPtr<U> && other)177 WeakPtr(WeakPtr<U>&& other) 178 : internal::WeakPtrBase(std::move(other)), ptr_(other.ptr_) {} 179 get()180 T* get() const { return ref_.is_valid() ? ptr_ : nullptr; } 181 182 T& operator*() const { 183 RTC_DCHECK(get() != nullptr); 184 return *get(); 185 } 186 T* operator->() const { 187 RTC_DCHECK(get() != nullptr); 188 return get(); 189 } 190 reset()191 void reset() { 192 ref_ = internal::WeakReference(); 193 ptr_ = nullptr; 194 } 195 196 // Allow conditionals to test validity, e.g. if (weak_ptr) {...}; 197 explicit operator bool() const { return get() != nullptr; } 198 199 private: 200 template <typename U> 201 friend class WeakPtr; 202 friend class WeakPtrFactory<T>; 203 WeakPtr(const internal::WeakReference & ref,T * ptr)204 WeakPtr(const internal::WeakReference& ref, T* ptr) 205 : internal::WeakPtrBase(ref), ptr_(ptr) {} 206 207 // This pointer is only valid when ref_.is_valid() is true. Otherwise, its 208 // value is undefined (as opposed to nullptr). 209 T* ptr_; 210 }; 211 212 // Allow callers to compare WeakPtrs against nullptr to test validity. 213 template <class T> 214 bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) { 215 return !(weak_ptr == nullptr); 216 } 217 template <class T> 218 bool operator!=(std::nullptr_t, const WeakPtr<T>& weak_ptr) { 219 return weak_ptr != nullptr; 220 } 221 template <class T> 222 bool operator==(const WeakPtr<T>& weak_ptr, std::nullptr_t) { 223 return weak_ptr.get() == nullptr; 224 } 225 template <class T> 226 bool operator==(std::nullptr_t, const WeakPtr<T>& weak_ptr) { 227 return weak_ptr == nullptr; 228 } 229 230 // A class may be composed of a WeakPtrFactory and thereby 231 // control how it exposes weak pointers to itself. This is helpful if you only 232 // need weak pointers within the implementation of a class. This class is also 233 // useful when working with primitive types. For example, you could have a 234 // WeakPtrFactory<bool> that is used to pass around a weak reference to a bool. 235 236 // Note that GetWeakPtr must be called on one and only one TaskQueue or thread 237 // and the WeakPtr must only be dereferenced and invalidated on that same 238 // TaskQueue/thread. A WeakPtr instance can be copied and posted to other 239 // sequences though as long as it is not dereferenced (WeakPtr<T>::get()). 240 template <class T> 241 class WeakPtrFactory { 242 public: WeakPtrFactory(T * ptr)243 explicit WeakPtrFactory(T* ptr) : ptr_(ptr) {} 244 245 WeakPtrFactory() = delete; 246 WeakPtrFactory(const WeakPtrFactory&) = delete; 247 WeakPtrFactory& operator=(const WeakPtrFactory&) = delete; 248 ~WeakPtrFactory()249 ~WeakPtrFactory() { ptr_ = nullptr; } 250 GetWeakPtr()251 WeakPtr<T> GetWeakPtr() { 252 RTC_DCHECK(ptr_); 253 return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_); 254 } 255 256 // Call this method to invalidate all existing weak pointers. InvalidateWeakPtrs()257 void InvalidateWeakPtrs() { 258 RTC_DCHECK(ptr_); 259 weak_reference_owner_.Invalidate(); 260 } 261 262 // Call this method to determine if any weak pointers exist. HasWeakPtrs()263 bool HasWeakPtrs() const { 264 RTC_DCHECK(ptr_); 265 return weak_reference_owner_.HasRefs(); 266 } 267 268 private: 269 internal::WeakReferenceOwner weak_reference_owner_; 270 T* ptr_; 271 }; 272 273 } // namespace rtc 274 275 #endif // RTC_BASE_WEAK_PTR_H_ 276