Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
weak_ptr.h
Go to the documentation of this file.
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
24
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.
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 {
84 return flag_ && flag_->is_valid();
85 }
86
87 T* get() const {
89 return *this ? ptr_ : nullptr;
90 }
91
92 T& operator*() const {
94 FML_DCHECK(*this);
95 return *get();
96 }
97
98 T* operator->() const {
100 FML_DCHECK(*this);
101 return get();
102 }
103
104 protected:
106 : ptr_(ptr), flag_(std::move(flag)) {}
107
108 void CheckThreadSafety() const {
110 }
111
112 private:
113 template <typename U>
114 friend class WeakPtr;
115
116 friend class WeakPtrFactory<T>;
117
118 explicit WeakPtr(T* ptr,
120 const DebugThreadChecker& checker)
121 : ptr_(ptr), flag_(std::move(flag)), checker_(checker) {}
122 T* ptr_;
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>
139 public:
140 TaskRunnerAffineWeakPtr() : ptr_(nullptr) {}
141
143
144 template <typename U>
145 // NOLINTNEXTLINE(google-explicit-constructor)
147 : ptr_(static_cast<T*>(r.ptr_)), flag_(r.flag_), checker_(r.checker_) {}
148
150
151 template <typename U>
152 // NOLINTNEXTLINE(google-explicit-constructor)
154 : ptr_(static_cast<T*>(r.ptr_)),
155 flag_(std::move(r.flag_)),
156 checker_(r.checker_) {}
157
159
161 default;
162
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 {
173 return flag_ && flag_->is_valid();
174 }
175
176 T* get() const {
178 return *this ? ptr_ : nullptr;
179 }
180
181 T& operator*() const {
183 FML_DCHECK(*this);
184 return *get();
185 }
186
187 T* operator->() const {
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>
201 friend class TaskRunnerAffineWeakPtrFactory<T>;
202
204 T* ptr,
206 const DebugTaskRunnerChecker& checker)
207 : ptr_(ptr), flag_(std::move(flag)), checker_(checker) {}
208
209 T* ptr_;
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>
258 public:
259 explicit WeakPtrFactory(T* ptr)
260 : ptr_(ptr), flag_(fml::MakeRefCounted<fml::internal::WeakPtrFlag>()) {
261 FML_DCHECK(ptr_);
262 }
263
265 CheckThreadSafety();
266 flag_->Invalidate();
267 }
268
269 // Gets a new weak pointer, which will be valid until this object is
270 // destroyed.
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_;
280
281 void CheckThreadSafety() const {
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>
294 public:
296 : ptr_(ptr), flag_(fml::MakeRefCounted<fml::internal::WeakPtrFlag>()) {
297 FML_DCHECK(ptr_);
298 }
299
301 CheckThreadSafety();
302 flag_->Invalidate();
303 }
304
305 // Gets a new weak pointer, which will be valid until this object is
306 // destroyed.
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_;
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_
RefPtr< T > Clone() const
Definition ref_ptr.h:184
TaskRunnerAffineWeakPtr< T > GetWeakPtr() const
Definition weak_ptr.h:307
TaskRunnerAffineWeakPtr(TaskRunnerAffineWeakPtr< T > &&r)=default
friend class TaskRunnerAffineWeakPtr
Definition weak_ptr.h:200
TaskRunnerAffineWeakPtr(const TaskRunnerAffineWeakPtr< T > &r)=default
void CheckThreadSafety() const
Definition weak_ptr.h:194
TaskRunnerAffineWeakPtr< T > & operator=(const TaskRunnerAffineWeakPtr< T > &r)=default
TaskRunnerAffineWeakPtr< T > & operator=(TaskRunnerAffineWeakPtr< T > &&r)=default
TaskRunnerAffineWeakPtr(const TaskRunnerAffineWeakPtr< U > &r)
Definition weak_ptr.h:146
TaskRunnerAffineWeakPtr(TaskRunnerAffineWeakPtr< U > &&r)
Definition weak_ptr.h:153
WeakPtr< T > GetWeakPtr() const
Definition weak_ptr.h:271
WeakPtrFactory(T *ptr)
Definition weak_ptr.h:259
T * get() const
Definition weak_ptr.h:87
void CheckThreadSafety() const
Definition weak_ptr.h:108
WeakPtr(WeakPtr< U > &&r)
Definition weak_ptr.h:63
friend class WeakPtr
Definition weak_ptr.h:114
T & operator*() const
Definition weak_ptr.h:92
WeakPtr(const WeakPtr< U > &r)
Definition weak_ptr.h:56
WeakPtr< T > & operator=(WeakPtr< T > &&r)=default
WeakPtr< T > & operator=(const WeakPtr< T > &r)=default
WeakPtr(T *ptr, fml::RefPtr< fml::internal::WeakPtrFlag > &&flag)
Definition weak_ptr.h:105
void reset()
Definition weak_ptr.h:77
WeakPtr(const WeakPtr< T > &r)=default
WeakPtr(WeakPtr< T > &&r)=default
T * operator->() const
Definition weak_ptr.h:98
FlutterSemanticsFlag flag
#define FML_DCHECK(condition)
Definition logging.h:103
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition macros.h:27
RefPtr< T > MakeRefCounted(Args &&... args)
Definition ref_ptr.h:248
Definition ref_ptr.h:256
#define T
FML_DECLARE_TASK_RUNNER_CHECKER(checker)
FML_DECLARE_THREAD_CHECKER(checker)
#define FML_DCHECK_TASK_RUNNER_IS_CURRENT(c)
#define FML_DCHECK_CREATION_THREAD_IS_CURRENT(c)