1 // Copyright 2013 The Flutter 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 // This file provides weak pointers and weak pointer factories that work like 6 // Chromium's |base::WeakPtr<T>| and |base::WeakPtrFactory<T>|. 7 8 #ifndef FLUTTER_FML_MEMORY_WEAK_PTR_H_ 9 #define FLUTTER_FML_MEMORY_WEAK_PTR_H_ 10 11 #include <utility> 12 13 #include "flutter/fml/logging.h" 14 #include "flutter/fml/memory/ref_counted.h" 15 #include "flutter/fml/memory/thread_checker.h" 16 #include "flutter/fml/memory/weak_ptr_internal.h" 17 18 namespace fml { 19 20 struct DebugThreadChecker { 21 FML_DECLARE_THREAD_CHECKER(checker); 22 }; 23 24 // Forward declaration, so |WeakPtr<T>| can friend it. 25 template <typename T> 26 class WeakPtrFactory; 27 28 // Class for "weak pointers" that can be invalidated. Valid weak pointers can 29 // only originate from a |WeakPtrFactory| (see below), though weak pointers are 30 // copyable and movable. 31 // 32 // Weak pointers are not in general thread-safe. They may only be *used* on a 33 // single thread, namely the same thread as the "originating" |WeakPtrFactory| 34 // (which can invalidate the weak pointers that it generates). 35 // 36 // However, weak pointers may be passed to other threads, reset on other 37 // threads, or destroyed on other threads. They may also be reassigned on other 38 // threads (in which case they should then only be used on the thread 39 // corresponding to the new "originating" |WeakPtrFactory|). 40 template <typename T> 41 class WeakPtr { 42 public: WeakPtr()43 WeakPtr() : ptr_(nullptr) {} 44 45 // Copy constructor. 46 WeakPtr(const WeakPtr<T>& r) = default; 47 48 template <typename U> WeakPtr(const WeakPtr<U> & r)49 WeakPtr(const WeakPtr<U>& r) 50 : ptr_(static_cast<T*>(r.ptr_)), flag_(r.flag_), checker_(r.checker_) {} 51 52 // Move constructor. 53 WeakPtr(WeakPtr<T>&& r) = default; 54 55 template <typename U> WeakPtr(WeakPtr<U> && r)56 WeakPtr(WeakPtr<U>&& r) 57 : ptr_(static_cast<T*>(r.ptr_)), 58 flag_(std::move(r.flag_)), 59 checker_(r.checker_) {} 60 61 ~WeakPtr() = default; 62 63 // The following methods are thread-friendly, in the sense that they may be 64 // called subject to additional synchronization. 65 66 // Copy assignment. 67 WeakPtr<T>& operator=(const WeakPtr<T>& r) = default; 68 69 // Move assignment. 70 WeakPtr<T>& operator=(WeakPtr<T>&& r) = default; 71 reset()72 void reset() { flag_ = nullptr; } 73 74 // The following methods should only be called on the same thread as the 75 // "originating" |WeakPtrFactory|. 76 77 explicit operator bool() const { 78 FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker); 79 return flag_ && flag_->is_valid(); 80 } 81 get()82 T* get() const { 83 FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker); 84 return *this ? ptr_ : nullptr; 85 } 86 87 T& operator*() const { 88 FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker); 89 FML_DCHECK(*this); 90 return *get(); 91 } 92 93 T* operator->() const { 94 FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker); 95 FML_DCHECK(*this); 96 return get(); 97 } 98 99 private: 100 template <typename U> 101 friend class WeakPtr; 102 103 friend class WeakPtrFactory<T>; 104 WeakPtr(T * ptr,fml::RefPtr<fml::internal::WeakPtrFlag> && flag,DebugThreadChecker checker)105 explicit WeakPtr(T* ptr, 106 fml::RefPtr<fml::internal::WeakPtrFlag>&& flag, 107 DebugThreadChecker checker) 108 : ptr_(ptr), flag_(std::move(flag)), checker_(checker) {} 109 110 T* ptr_; 111 fml::RefPtr<fml::internal::WeakPtrFlag> flag_; 112 DebugThreadChecker checker_; 113 114 // Copy/move construction/assignment supported. 115 }; 116 117 // Class that produces (valid) |WeakPtr<T>|s. Typically, this is used as a 118 // member variable of |T| (preferably the last one -- see below), and |T|'s 119 // methods control how weak pointers to it are vended. This class is not 120 // thread-safe, and should only be created, destroyed and used on a single 121 // thread. 122 // 123 // Example: 124 // 125 // class Controller { 126 // public: 127 // Controller() : ..., weak_factory_(this) {} 128 // ... 129 // 130 // void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); } 131 // void WorkComplete(const Result& result) { ... } 132 // 133 // private: 134 // ... 135 // 136 // // Member variables should appear before the |WeakPtrFactory|, to ensure 137 // // that any |WeakPtr|s to |Controller| are invalidated before its member 138 // // variables' destructors are executed. 139 // WeakPtrFactory<Controller> weak_factory_; 140 // }; 141 // 142 // class Worker { 143 // public: 144 // static void StartNew(const WeakPtr<Controller>& controller) { 145 // Worker* worker = new Worker(controller); 146 // // Kick off asynchronous processing.... 147 // } 148 // 149 // private: 150 // Worker(const WeakPtr<Controller>& controller) : controller_(controller) {} 151 // 152 // void DidCompleteAsynchronousProcessing(const Result& result) { 153 // if (controller_) 154 // controller_->WorkComplete(result); 155 // } 156 // 157 // WeakPtr<Controller> controller_; 158 // }; 159 template <typename T> 160 class WeakPtrFactory { 161 public: WeakPtrFactory(T * ptr)162 explicit WeakPtrFactory(T* ptr) 163 : ptr_(ptr), flag_(fml::MakeRefCounted<fml::internal::WeakPtrFlag>()) { 164 FML_DCHECK(ptr_); 165 } 166 ~WeakPtrFactory()167 ~WeakPtrFactory() { 168 FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker); 169 flag_->Invalidate(); 170 } 171 172 // Gets a new weak pointer, which will be valid until either 173 // |InvalidateWeakPtrs()| is called or this object is destroyed. GetWeakPtr()174 WeakPtr<T> GetWeakPtr() const { 175 return WeakPtr<T>(ptr_, flag_.Clone(), checker_); 176 } 177 178 private: 179 // Note: See weak_ptr_internal.h for an explanation of why we store the 180 // pointer here, instead of in the "flag". 181 T* const ptr_; 182 fml::RefPtr<fml::internal::WeakPtrFlag> flag_; 183 DebugThreadChecker checker_; 184 185 FML_DISALLOW_COPY_AND_ASSIGN(WeakPtrFactory); 186 }; 187 188 } // namespace fml 189 190 #endif // FLUTTER_FML_MEMORY_WEAK_PTR_H_ 191