Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 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 // This file provides weak pointers and weak pointer factories that work like | |
| 6 // Chromium's |base::WeakPtr<T>| and |base::WeakPtrFactory<T>|. Note that we do | |
| 7 // not provide anything analogous to |base::SupportsWeakPtr<T>|. | |
| 8 | |
| 9 #ifndef MOJO_UTIL_WEAK_PTR_H_ | |
| 10 #define MOJO_UTIL_WEAK_PTR_H_ | |
| 11 | |
| 12 #include <assert.h> | |
| 13 | |
| 14 #include <utility> | |
| 15 | |
| 16 #include "mojo/edk/util/ref_ptr.h" | |
| 17 #include "mojo/edk/util/weak_ptr_internal.h" | |
| 18 | |
| 19 namespace mojo { | |
| 20 namespace util { | |
| 21 | |
| 22 // Forward declaration, so |WeakPtr<T>| can friend it. | |
| 23 template <typename T> | |
| 24 class WeakPtrFactory; | |
| 25 | |
| 26 // Class for "weak pointers" that can be invalidated. Valid weak pointers can | |
| 27 // only originate from a |WeakPtrFactory| (see below), though weak pointers are | |
| 28 // copyable and movable. | |
| 29 // | |
| 30 // Weak pointers are not in general thread-safe. They may only be *used* on a | |
| 31 // single thread, namely the same thread as the "originating" |WeakPtrFactory| | |
| 32 // (which can invalidate the weak pointers that it generates). | |
| 33 // | |
| 34 // However, weak pointers may be passed to other threads, reset on other | |
| 35 // threads, or destroyed on other threads. They may also be reassigned on other | |
| 36 // threads (in which case they should then only be used on the thread | |
| 37 // corresponding to the new "originating" |WeakPtrFactory|). | |
| 38 template <typename T> | |
| 39 class WeakPtr { | |
| 40 public: | |
| 41 WeakPtr() : ptr_(nullptr) {} | |
| 42 | |
| 43 // Copy constructor. | |
| 44 WeakPtr(const WeakPtr<T>& r) = default; | |
| 45 | |
| 46 template <typename U> | |
| 47 WeakPtr(const WeakPtr<U>& r) : ptr_(r.ptr_), flag_(r.flag_) {} | |
| 48 | |
| 49 // Move constructor. | |
| 50 WeakPtr(WeakPtr<T>&& r) = default; | |
| 51 | |
| 52 template <typename U> | |
| 53 WeakPtr(WeakPtr<U>&& r) : ptr_(r.ptr_), flag_(std::move(r.flag_)) {} | |
| 54 | |
| 55 ~WeakPtr() = default; | |
| 56 | |
| 57 // The following methods are thread-friendly, in the sense that they may be | |
| 58 // called subject to additional synchronization. | |
| 59 | |
| 60 // Copy assignment. | |
| 61 WeakPtr<T>& operator=(const WeakPtr<T>& r) = default; | |
| 62 | |
| 63 template <typename U> | |
| 64 WeakPtr<T>& operator=(const WeakPtr<T>& r) { | |
| 65 ptr_ = r.ptr_; | |
| 66 flag_ = r.flag_; | |
| 67 } | |
| 68 | |
| 69 // Move assignment. | |
| 70 WeakPtr<T>& operator=(WeakPtr<T>&& r) = default; | |
| 71 | |
| 72 template <typename U> | |
| 73 WeakPtr<T>& operator=(WeakPtr<T>&& r) { | |
| 74 ptr_ = r.ptr_; | |
| 75 flag_ = std::move(r.flag_); | |
| 76 } | |
| 77 | |
| 78 void reset() { flag_ = nullptr; } | |
| 79 | |
| 80 // The following methods should only be called on the same thread as the | |
| 81 // "originating" |WeakPtrFactory| (subject to the additional explanatory | |
| 82 // commentary). | |
| 83 | |
| 84 // This is thread-friendly (subject to synchronization), but only a "false" | |
| 85 // result is definitive on threads other than the "originating" | |
|
jamesr
2016/01/28 23:56:55
I think this is untrue - any return value is poten
viettrungluu
2016/01/29 00:03:39
Oops, comment removed.
| |
| 86 // |WeakPtrFactory|'s thread. (Similarly, |get()| is thread-friendly, but only | |
| 87 // the null result is definitive.) | |
| 88 explicit operator bool() const { return flag_ && flag_->is_valid(); } | |
| 89 | |
| 90 T* get() const { return *this ? ptr_ : nullptr; } | |
| 91 | |
| 92 T& operator*() const { | |
| 93 assert(*this); | |
| 94 return *get(); | |
| 95 } | |
| 96 | |
| 97 T* operator->() const { | |
| 98 assert(*this); | |
| 99 return get(); | |
| 100 } | |
| 101 | |
| 102 private: | |
| 103 template <typename U> | |
| 104 friend class WeakPtr; | |
| 105 | |
| 106 friend class WeakPtrFactory<T>; | |
| 107 | |
| 108 explicit WeakPtr(T* ptr, RefPtr<internal::WeakPtrFlag>&& flag) | |
| 109 : ptr_(ptr), flag_(std::move(flag)) {} | |
| 110 | |
| 111 T* ptr_; | |
| 112 RefPtr<internal::WeakPtrFlag> flag_; | |
| 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 used on a single thread. | |
| 121 // | |
| 122 // Example: | |
| 123 // | |
| 124 // class Controller { | |
| 125 // public: | |
| 126 // Controller() : ..., weak_factory_(this) {} | |
| 127 // ... | |
| 128 // | |
| 129 // void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); } | |
| 130 // void WorkComplete(const Result& result) { ... } | |
| 131 // | |
| 132 // private: | |
| 133 // ... | |
| 134 // | |
| 135 // // Member variables should appear before the |WeakPtrFactory|, to ensure | |
| 136 // // that any |WeakPtr|s to |Controller| are invalidated before its member | |
| 137 // // variables' destructors are executed. | |
| 138 // WeakPtrFactory<Controller> weak_factory_; | |
| 139 // }; | |
| 140 // | |
| 141 // class Worker { | |
| 142 // public: | |
| 143 // static void StartNew(const WeakPtr<Controller>& controller) { | |
| 144 // Worker* worker = new Worker(controller); | |
| 145 // // Kick off asynchronous processing.... | |
| 146 // } | |
| 147 // | |
| 148 // private: | |
| 149 // Worker(const WeakPtr<Controller>& controller) : controller_(controller) {} | |
| 150 // | |
| 151 // void DidCompleteAsynchronousProcessing(const Result& result) { | |
| 152 // if (controller_) | |
| 153 // controller_->WorkComplete(result); | |
| 154 // } | |
| 155 // | |
| 156 // WeakPtr<Controller> controller_; | |
| 157 // }; | |
| 158 template <typename T> | |
| 159 class WeakPtrFactory { | |
| 160 public: | |
| 161 explicit WeakPtrFactory(T* ptr) : ptr_(ptr) { assert(ptr_); } | |
| 162 ~WeakPtrFactory() { InvalidateWeakPtrs(); } | |
| 163 | |
| 164 // Gets a new weak pointer, which will be valid until either | |
| 165 // |InvalidateWeakPtrs()| is called or this object is destroyed. | |
| 166 WeakPtr<T> GetWeakPtr() { | |
| 167 if (!flag_) | |
| 168 flag_ = MakeRefCounted<internal::WeakPtrFlag>(); | |
| 169 return WeakPtr<T>(ptr_, flag_.Clone()); | |
| 170 } | |
| 171 | |
| 172 // Call this method to invalidate all existing weak pointers. (Note that | |
| 173 // additional weak pointers can be produced even after this is called.) | |
| 174 void InvalidateWeakPtrs() { | |
| 175 if (!flag_) | |
| 176 return; | |
| 177 flag_->Invalidate(); | |
| 178 flag_ = nullptr; | |
| 179 } | |
| 180 | |
| 181 // Call this method to determine if any weak pointers exist. (Note that a | |
| 182 // "false" result is definitive, but a "true" result may not be if weak | |
| 183 // pointers are held/reset/destroyed/reassigned on other threads.) | |
| 184 bool HasWeakPtrs() const { return flag_ && !flag_->HasOneRef(); } | |
| 185 | |
| 186 private: | |
| 187 // Note: See weak_ptr_internal.h for an explanation of why we store the | |
| 188 // pointer here, instead of in the "flag". | |
| 189 T* const ptr_; | |
| 190 RefPtr<internal::WeakPtrFlag> flag_; | |
| 191 | |
| 192 MOJO_DISALLOW_COPY_AND_ASSIGN(WeakPtrFactory); | |
| 193 }; | |
| 194 | |
| 195 } // namespace util | |
| 196 } // namespace mojo | |
| 197 | |
| 198 #endif // MOJO_UTIL_WEAK_PTR_H_ | |
| OLD | NEW |