Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: mojo/edk/util/weak_ptr.h

Issue 1646113002: Bring in a reduced/simplified version of Chromium's base::WeakPtr to //mojo/edk/util. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: review Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/edk/util/BUILD.gn ('k') | mojo/edk/util/weak_ptr_internal.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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|.
82
83 explicit operator bool() const { return flag_ && flag_->is_valid(); }
84
85 T* get() const { return *this ? ptr_ : nullptr; }
86
87 T& operator*() const {
88 assert(*this);
89 return *get();
90 }
91
92 T* operator->() const {
93 assert(*this);
94 return get();
95 }
96
97 private:
98 template <typename U>
99 friend class WeakPtr;
100
101 friend class WeakPtrFactory<T>;
102
103 explicit WeakPtr(T* ptr, RefPtr<internal::WeakPtrFlag>&& flag)
104 : ptr_(ptr), flag_(std::move(flag)) {}
105
106 T* ptr_;
107 RefPtr<internal::WeakPtrFlag> flag_;
108
109 // Copy/move construction/assignment supported.
110 };
111
112 // Class that produces (valid) |WeakPtr<T>|s. Typically, this is used as a
113 // member variable of |T| (preferably the last one -- see below), and |T|'s
114 // methods control how weak pointers to it are vended. This class is not
115 // thread-safe, and should only be used on a single thread.
116 //
117 // Example:
118 //
119 // class Controller {
120 // public:
121 // Controller() : ..., weak_factory_(this) {}
122 // ...
123 //
124 // void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); }
125 // void WorkComplete(const Result& result) { ... }
126 //
127 // private:
128 // ...
129 //
130 // // Member variables should appear before the |WeakPtrFactory|, to ensure
131 // // that any |WeakPtr|s to |Controller| are invalidated before its member
132 // // variables' destructors are executed.
133 // WeakPtrFactory<Controller> weak_factory_;
134 // };
135 //
136 // class Worker {
137 // public:
138 // static void StartNew(const WeakPtr<Controller>& controller) {
139 // Worker* worker = new Worker(controller);
140 // // Kick off asynchronous processing....
141 // }
142 //
143 // private:
144 // Worker(const WeakPtr<Controller>& controller) : controller_(controller) {}
145 //
146 // void DidCompleteAsynchronousProcessing(const Result& result) {
147 // if (controller_)
148 // controller_->WorkComplete(result);
149 // }
150 //
151 // WeakPtr<Controller> controller_;
152 // };
153 template <typename T>
154 class WeakPtrFactory {
155 public:
156 explicit WeakPtrFactory(T* ptr) : ptr_(ptr) { assert(ptr_); }
157 ~WeakPtrFactory() { InvalidateWeakPtrs(); }
158
159 // Gets a new weak pointer, which will be valid until either
160 // |InvalidateWeakPtrs()| is called or this object is destroyed.
161 WeakPtr<T> GetWeakPtr() {
162 if (!flag_)
163 flag_ = MakeRefCounted<internal::WeakPtrFlag>();
164 return WeakPtr<T>(ptr_, flag_.Clone());
165 }
166
167 // Call this method to invalidate all existing weak pointers. (Note that
168 // additional weak pointers can be produced even after this is called.)
169 void InvalidateWeakPtrs() {
170 if (!flag_)
171 return;
172 flag_->Invalidate();
173 flag_ = nullptr;
174 }
175
176 // Call this method to determine if any weak pointers exist. (Note that a
177 // "false" result is definitive, but a "true" result may not be if weak
178 // pointers are held/reset/destroyed/reassigned on other threads.)
179 bool HasWeakPtrs() const { return flag_ && !flag_->HasOneRef(); }
180
181 private:
182 // Note: See weak_ptr_internal.h for an explanation of why we store the
183 // pointer here, instead of in the "flag".
184 T* const ptr_;
185 RefPtr<internal::WeakPtrFlag> flag_;
186
187 MOJO_DISALLOW_COPY_AND_ASSIGN(WeakPtrFactory);
188 };
189
190 } // namespace util
191 } // namespace mojo
192
193 #endif // MOJO_UTIL_WEAK_PTR_H_
OLDNEW
« no previous file with comments | « mojo/edk/util/BUILD.gn ('k') | mojo/edk/util/weak_ptr_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698