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/task_runner_checker.h"
16#include "flutter/fml/memory/thread_checker.h"
17#include "flutter/fml/memory/weak_ptr_internal.h"
18
19namespace fml {
20
21struct DebugThreadChecker {
22 FML_DECLARE_THREAD_CHECKER(checker);
23};
24
25struct DebugTaskRunnerChecker {
26 FML_DECLARE_TASK_RUNNER_CHECKER(checker);
27};
28
29// Forward declaration, so |WeakPtr<T>| can friend it.
30template <typename T>
31class WeakPtrFactory;
32
33// Class for "weak pointers" that can be invalidated. Valid weak pointers
34// can only originate from a |WeakPtrFactory| (see below), though weak
35// pointers are copyable and movable.
36//
37// Weak pointers are not in general thread-safe. They may only be *used* on
38// a single thread, namely the same thread as the "originating"
39// |WeakPtrFactory| (which can invalidate the weak pointers that it
40// generates).
41//
42// However, weak pointers may be passed to other threads, reset on other
43// threads, or destroyed on other threads. They may also be reassigned on
44// other threads (in which case they should then only be used on the thread
45// corresponding to the new "originating" |WeakPtrFactory|).
46template <typename T>
47class WeakPtr {
48 public:
49 WeakPtr() : ptr_(nullptr) {}
50
51 // Copy constructor.
52 // NOLINTNEXTLINE(google-explicit-constructor)
53 WeakPtr(const WeakPtr<T>& r) = default;
54
55 template <typename U>
56 WeakPtr(const WeakPtr<U>& r) // NOLINT(google-explicit-constructor)
57 : ptr_(static_cast<T*>(r.ptr_)), flag_(r.flag_), checker_(r.checker_) {}
58
59 // Move constructor.
60 WeakPtr(WeakPtr<T>&& r) = default;
61
62 template <typename U>
63 WeakPtr(WeakPtr<U>&& r) // NOLINT(google-explicit-constructor)
64 : ptr_(static_cast<T*>(r.ptr_)),
65 flag_(std::move(r.flag_)),
66 checker_(r.checker_) {}
67
68 // The following methods are thread-friendly, in the sense that they may be
69 // called subject to additional synchronization.
70
71 // Copy assignment.
72 WeakPtr<T>& operator=(const WeakPtr<T>& r) = default;
73
74 // Move assignment.
75 WeakPtr<T>& operator=(WeakPtr<T>&& r) = default;
76
77 void reset() { flag_ = nullptr; }
78
79 // The following methods should only be called on the same thread as the
80 // "originating" |WeakPtrFactory|.
81
82 explicit operator bool() const {
83 CheckThreadSafety();
84 return flag_ && flag_->is_valid();
85 }
86
87 T* get() const {
88 CheckThreadSafety();
89 return *this ? ptr_ : nullptr;
90 }
91
92 T& operator*() const {
93 CheckThreadSafety();
94 FML_DCHECK(*this);
95 return *get();
96 }
97
98 T* operator->() const {
99 CheckThreadSafety();
100 FML_DCHECK(*this);
101 return get();
102 }
103
104 protected:
105 explicit WeakPtr(T* ptr, fml::RefPtr<fml::internal::WeakPtrFlag>&& flag)
106 : ptr_(ptr), flag_(std::move(flag)) {}
107
108 void CheckThreadSafety() const {
109 FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker);
110 }
111
112 private:
113 template <typename U>
114 friend class WeakPtr;
115
116 friend class WeakPtrFactory<T>;
117
118 explicit WeakPtr(T* ptr,
119 fml::RefPtr<fml::internal::WeakPtrFlag>&& flag,
120 DebugThreadChecker checker)
121 : ptr_(ptr), flag_(std::move(flag)), checker_(checker) {}
122 T* ptr_;
123 fml::RefPtr<fml::internal::WeakPtrFlag> flag_;
124 DebugThreadChecker checker_;
125
126 // Copy/move construction/assignment supported.
127};
128
129// Forward declaration, so |TaskRunnerAffineWeakPtr<T>| can friend it.
130template <typename T>
131class TaskRunnerAffineWeakPtrFactory;
132
133// A weak pointer that can be used in different threads as long as
134// the threads are belong to the same |TaskRunner|.
135//
136// It is still not in general thread safe as |WeakPtr|.
137template <typename T>
138class TaskRunnerAffineWeakPtr {
139 public:
140 TaskRunnerAffineWeakPtr() : ptr_(nullptr) {}
141
142 TaskRunnerAffineWeakPtr(const TaskRunnerAffineWeakPtr<T>& r) = default;
143
144 template <typename U>
145 // NOLINTNEXTLINE(google-explicit-constructor)
146 TaskRunnerAffineWeakPtr(const TaskRunnerAffineWeakPtr<U>& r)
147 : ptr_(static_cast<T*>(r.ptr_)), flag_(r.flag_), checker_(r.checker_) {}
148
149 TaskRunnerAffineWeakPtr(TaskRunnerAffineWeakPtr<T>&& r) = default;
150
151 template <typename U>
152 // NOLINTNEXTLINE(google-explicit-constructor)
153 TaskRunnerAffineWeakPtr(TaskRunnerAffineWeakPtr<U>&& r)
154 : ptr_(static_cast<T*>(r.ptr_)),
155 flag_(std::move(r.flag_)),
156 checker_(r.checker_) {}
157
158 ~TaskRunnerAffineWeakPtr() = default;
159
160 TaskRunnerAffineWeakPtr<T>& operator=(const TaskRunnerAffineWeakPtr<T>& r) =
161 default;
162
163 TaskRunnerAffineWeakPtr<T>& operator=(TaskRunnerAffineWeakPtr<T>&& r) =
164 default;
165
166 void reset() { flag_ = nullptr; }
167
168 // The following methods should only be called on the same thread as the
169 // "originating" |TaskRunnerAffineWeakPtrFactory|.
170
171 explicit operator bool() const {
172 CheckThreadSafety();
173 return flag_ && flag_->is_valid();
174 }
175
176 T* get() const {
177 CheckThreadSafety();
178 return *this ? ptr_ : nullptr;
179 }
180
181 T& operator*() const {
182 CheckThreadSafety();
183 FML_DCHECK(*this);
184 return *get();
185 }
186
187 T* operator->() const {
188 CheckThreadSafety();
189 FML_DCHECK(*this);
190 return get();
191 }
192
193 protected:
194 void CheckThreadSafety() const {
195 FML_DCHECK_TASK_RUNNER_IS_CURRENT(checker_.checker);
196 }
197
198 private:
199 template <typename U>
200 friend class TaskRunnerAffineWeakPtr;
201 friend class TaskRunnerAffineWeakPtrFactory<T>;
202
203 explicit TaskRunnerAffineWeakPtr(
204 T* ptr,
205 fml::RefPtr<fml::internal::WeakPtrFlag>&& flag,
206 DebugTaskRunnerChecker checker)
207 : ptr_(ptr), flag_(std::move(flag)), checker_(checker) {}
208
209 T* ptr_;
210 fml::RefPtr<fml::internal::WeakPtrFlag> flag_;
211 DebugTaskRunnerChecker checker_;
212};
213
214// Class that produces (valid) |WeakPtr<T>|s. Typically, this is used as a
215// member variable of |T| (preferably the last one -- see below), and |T|'s
216// methods control how weak pointers to it are vended. This class is not
217// thread-safe, and should only be created, destroyed and used on a single
218// thread.
219//
220// Example:
221//
222// class Controller {
223// public:
224// Controller() : ..., weak_factory_(this) {}
225// ...
226//
227// void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); }
228// void WorkComplete(const Result& result) { ... }
229//
230// private:
231// ...
232//
233// // Member variables should appear before the |WeakPtrFactory|, to ensure
234// // that any |WeakPtr|s to |Controller| are invalidated before its member
235// // variables' destructors are executed.
236// WeakPtrFactory<Controller> weak_factory_;
237// };
238//
239// class Worker {
240// public:
241// static void StartNew(const WeakPtr<Controller>& controller) {
242// Worker* worker = new Worker(controller);
243// // Kick off asynchronous processing....
244// }
245//
246// private:
247// Worker(const WeakPtr<Controller>& controller) : controller_(controller) {}
248//
249// void DidCompleteAsynchronousProcessing(const Result& result) {
250// if (controller_)
251// controller_->WorkComplete(result);
252// }
253//
254// WeakPtr<Controller> controller_;
255// };
256template <typename T>
257class WeakPtrFactory {
258 public:
259 explicit WeakPtrFactory(T* ptr)
260 : ptr_(ptr), flag_(fml::MakeRefCounted<fml::internal::WeakPtrFlag>()) {
261 FML_DCHECK(ptr_);
262 }
263
264 ~WeakPtrFactory() {
265 CheckThreadSafety();
266 flag_->Invalidate();
267 }
268
269 // Gets a new weak pointer, which will be valid until this object is
270 // destroyed.
271 WeakPtr<T> GetWeakPtr() const {
272 return WeakPtr<T>(ptr_, flag_.Clone(), checker_);
273 }
274
275 private:
276 // Note: See weak_ptr_internal.h for an explanation of why we store the
277 // pointer here, instead of in the "flag".
278 T* const ptr_;
279 fml::RefPtr<fml::internal::WeakPtrFlag> flag_;
280
281 void CheckThreadSafety() const {
282 FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker_.checker);
283 }
284
285 DebugThreadChecker checker_;
286
287 FML_DISALLOW_COPY_AND_ASSIGN(WeakPtrFactory);
288};
289
290// A type of |WeakPtrFactory| that produces |TaskRunnerAffineWeakPtr| instead of
291// |WeakPtr|.
292template <typename T>
293class TaskRunnerAffineWeakPtrFactory {
294 public:
295 explicit TaskRunnerAffineWeakPtrFactory(T* ptr)
296 : ptr_(ptr), flag_(fml::MakeRefCounted<fml::internal::WeakPtrFlag>()) {
297 FML_DCHECK(ptr_);
298 }
299
300 ~TaskRunnerAffineWeakPtrFactory() {
301 CheckThreadSafety();
302 flag_->Invalidate();
303 }
304
305 // Gets a new weak pointer, which will be valid until this object is
306 // destroyed.
307 TaskRunnerAffineWeakPtr<T> GetWeakPtr() const {
308 return TaskRunnerAffineWeakPtr<T>(ptr_, flag_.Clone(), checker_);
309 }
310
311 private:
312 // Note: See weak_ptr_internal.h for an explanation of why we store the
313 // pointer here, instead of in the "flag".
314 T* const ptr_;
315 fml::RefPtr<fml::internal::WeakPtrFlag> flag_;
316
317 void CheckThreadSafety() const {
318 FML_DCHECK_TASK_RUNNER_IS_CURRENT(checker_.checker);
319 }
320
321 DebugTaskRunnerChecker checker_;
322
323 FML_DISALLOW_COPY_AND_ASSIGN(TaskRunnerAffineWeakPtrFactory);
324};
325
326} // namespace fml
327
328#endif // FLUTTER_FML_MEMORY_WEAK_PTR_H_
329

source code of flutter_engine/flutter/fml/memory/weak_ptr.h