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

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: 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
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| (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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698