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