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 |