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

Side by Side Diff: chrome/browser/sync/weak_handle.h

Issue 7572010: [Sync] Avoid leaking in WeakHandle even when the owner thread is gone (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 9 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | chrome/browser/sync/weak_handle.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Weak handles provides a way to refer to weak pointers from another 5 // Weak handles provides a way to refer to weak pointers from another
6 // thread. This is useful because it is not safe to reference a weak 6 // thread. This is useful because it is not safe to reference a weak
7 // pointer from a thread other than the thread on which it was 7 // pointer from a thread other than the thread on which it was
8 // created. 8 // created.
9 // 9 //
10 // Weak handles can be passed across threads, so for example, you can 10 // Weak handles can be passed across threads, so for example, you can
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 50
51 #include <cstddef> 51 #include <cstddef>
52 52
53 #include "base/basictypes.h" 53 #include "base/basictypes.h"
54 #include "base/bind.h" 54 #include "base/bind.h"
55 #include "base/callback.h" 55 #include "base/callback.h"
56 #include "base/compiler_specific.h" 56 #include "base/compiler_specific.h"
57 #include "base/logging.h" 57 #include "base/logging.h"
58 #include "base/memory/ref_counted.h" 58 #include "base/memory/ref_counted.h"
59 #include "base/memory/weak_ptr.h" 59 #include "base/memory/weak_ptr.h"
60 #include "base/message_loop_proxy.h" 60 #include "base/message_loop.h"
61 #include "base/tracked.h" 61 #include "base/tracked.h"
62 62
63 namespace base {
64 class MessageLoopProxy;
65 } // namespace base
66
63 namespace tracked_objects { 67 namespace tracked_objects {
64 class Location; 68 class Location;
65 } // namespace tracked_objects 69 } // namespace tracked_objects
66 70
67 namespace browser_sync { 71 namespace browser_sync {
68 72
69 template <typename T> class WeakHandle; 73 template <typename T> class WeakHandle;
70 74
71 namespace internal { 75 namespace internal {
72 // These classes are part of the WeakHandle implementation. DO NOT 76 // These classes are part of the WeakHandle implementation. DO NOT
(...skipping 14 matching lines...) Expand all
87 template <typename T, size_t n> 91 template <typename T, size_t n>
88 struct ParamTraits<T[n]> { 92 struct ParamTraits<T[n]> {
89 typedef const T* ForwardType; 93 typedef const T* ForwardType;
90 }; 94 };
91 95
92 template <typename T> 96 template <typename T>
93 struct ParamTraits<T[]> { 97 struct ParamTraits<T[]> {
94 typedef const T* ForwardType; 98 typedef const T* ForwardType;
95 }; 99 };
96 100
101 class WeakHandleCoreBase;
102
103 struct WeakHandleCoreBaseTraits {
104 static void Destruct(const WeakHandleCoreBase* core_base);
105 };
106
97 // Base class for WeakHandleCore<T> to avoid template bloat. Handles 107 // Base class for WeakHandleCore<T> to avoid template bloat. Handles
98 // the trampolining to the MessageLoopProxy for the owner thread. 108 // the interaction with the owner thread and its message loop.
99 // 109 class WeakHandleCoreBase
100 // This class is thread-safe. 110 : public MessageLoop::DestructionObserver,
101 class WeakHandleCoreBase { 111 public base::RefCountedThreadSafe<WeakHandleCoreBase,
112 WeakHandleCoreBaseTraits> {
102 public: 113 public:
103 // Assumes the current thread is the owner thread. 114 // Assumes the current thread is the owner thread.
104 WeakHandleCoreBase(); 115 WeakHandleCoreBase();
105 116
117 // May be called on any thread.
106 bool IsOnOwnerThread() const; 118 bool IsOnOwnerThread() const;
107 119
120 // MessageLoop::DestructionObserver implementation. Must be called
121 // on the owner thread.
122 virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
123
108 protected: 124 protected:
109 ~WeakHandleCoreBase(); 125 // May be deleted on any thread, but only via DestroyAndDelete()
126 // which is called by our traits class.
127 virtual ~WeakHandleCoreBase();
110 128
111 void PostOnOwnerThread(const tracked_objects::Location& from_here, 129 // This is called exactly once on the owner thread right before this
130 // object is destroyed or when the owner thread is destroyed,
131 // whichever comes first. Overridden by WeakHandle<T> (which also
132 // calls WeakHandleCoreBase::CleanupOnOwnerThread()).
133 virtual void CleanupOnOwnerThread();
134
135 // May be called on any thread.
136 void PostToOwnerThread(const tracked_objects::Location& from_here,
112 const base::Closure& fn) const; 137 const base::Closure& fn) const;
113 138
114 template <typename T> 139 private:
115 void DeleteOnOwnerThread(const tracked_objects::Location& from_here, 140 friend struct WeakHandleCoreBaseTraits;
116 const T* ptr) const {
117 if (IsOnOwnerThread()) {
118 delete ptr;
119 } else {
120 ignore_result(message_loop_proxy_->DeleteSoon(from_here, ptr));
121 }
122 }
123 141
124 private: 142 // May be called on any thread, but only via
125 const scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; 143 // WeakHandleCoreBaseTraits::Destruct(). Destroys and deletes this
144 // object.
145 void Destroy();
146
147 // Calls CleanupOnOwnerThread() and deletes |this|. Must be called
148 // on the owner thread via Destroy().
149 void CleanupAndDestroyOnOwnerThread();
150
151 // May be read on any thread, but should only be dereferenced on the
152 // owner thread.
153 MessageLoop* const owner_loop_;
154
155 // May be used on any thread.
156 const scoped_refptr<base::MessageLoopProxy> owner_loop_proxy_;
157
158 // Should only be read on the owner thread or in the destructor.
159 // Used only for CHECKs.
160 bool destroyed_on_owner_thread_;
126 161
127 DISALLOW_COPY_AND_ASSIGN(WeakHandleCoreBase); 162 DISALLOW_COPY_AND_ASSIGN(WeakHandleCoreBase);
128 }; 163 };
129 164
130 // WeakHandleCore<T> contains all the logic for WeakHandle<T>. 165 // WeakHandleCore<T> contains all the logic for WeakHandle<T>.
131 template <typename T> 166 template <typename T>
132 class WeakHandleCore 167 class WeakHandleCore : public WeakHandleCoreBase {
133 : public WeakHandleCoreBase,
134 public base::RefCountedThreadSafe<WeakHandleCore<T> > {
135 public: 168 public:
136 // Must be called on |ptr|'s owner thread, which is assumed to be 169 // Must be called on |ptr|'s owner thread, which is assumed to be
137 // the current thread. 170 // the current thread.
138 explicit WeakHandleCore(const base::WeakPtr<T>& ptr) 171 explicit WeakHandleCore(const base::WeakPtr<T>& ptr)
139 : ptr_(new base::WeakPtr<T>(ptr)) {} 172 : ptr_(new base::WeakPtr<T>(ptr)) {}
140 173
141 // May be destroyed on any thread.
142 ~WeakHandleCore() {
143 DeleteOnOwnerThread(FROM_HERE, ptr_);
144 }
145
146 // Must be called on |ptr_|'s owner thread. 174 // Must be called on |ptr_|'s owner thread.
147 const base::WeakPtr<T>& Get() const { 175 base::WeakPtr<T> Get() const {
148 CHECK(IsOnOwnerThread()); 176 CHECK(IsOnOwnerThread());
149 return *ptr_; 177 return ptr_ ? *ptr_ : base::WeakPtr<T>();
150 } 178 }
151 179
152 // Call(...) may be called on any thread, but all its arguments 180 // Call(...) may be called on any thread, but all its arguments
153 // should be safe to be bound and copied across threads. 181 // should be safe to be bound and copied across threads.
154 182
155 template <typename U> 183 template <typename U>
156 void Call(const tracked_objects::Location& from_here, 184 void Call(const tracked_objects::Location& from_here,
157 void (U::*fn)(void)) const { 185 void (U::*fn)(void)) const {
158 PostOnOwnerThread( 186 PostToOwnerThread(
159 from_here, 187 from_here,
160 Bind(&WeakHandleCore::template DoCall0<U>, this, fn)); 188 Bind(&WeakHandleCore::template DoCall0<U>, this, fn));
161 } 189 }
162 190
163 template <typename U, typename A1> 191 template <typename U, typename A1>
164 void Call(const tracked_objects::Location& from_here, 192 void Call(const tracked_objects::Location& from_here,
165 void (U::*fn)(A1), 193 void (U::*fn)(A1),
166 typename ParamTraits<A1>::ForwardType a1) const { 194 typename ParamTraits<A1>::ForwardType a1) const {
167 PostOnOwnerThread( 195 PostToOwnerThread(
168 from_here, 196 from_here,
169 Bind(&WeakHandleCore::template DoCall1<U, A1>, 197 Bind(&WeakHandleCore::template DoCall1<U, A1>,
170 this, fn, a1)); 198 this, fn, a1));
171 } 199 }
172 200
173 template <typename U, typename A1, typename A2> 201 template <typename U, typename A1, typename A2>
174 void Call(const tracked_objects::Location& from_here, 202 void Call(const tracked_objects::Location& from_here,
175 void (U::*fn)(A1, A2), 203 void (U::*fn)(A1, A2),
176 typename ParamTraits<A1>::ForwardType a1, 204 typename ParamTraits<A1>::ForwardType a1,
177 typename ParamTraits<A2>::ForwardType a2) const { 205 typename ParamTraits<A2>::ForwardType a2) const {
178 PostOnOwnerThread( 206 PostToOwnerThread(
179 from_here, 207 from_here,
180 Bind(&WeakHandleCore::template DoCall2<U, A1, A2>, 208 Bind(&WeakHandleCore::template DoCall2<U, A1, A2>,
181 this, fn, a1, a2)); 209 this, fn, a1, a2));
182 } 210 }
183 211
184 template <typename U, typename A1, typename A2, typename A3> 212 template <typename U, typename A1, typename A2, typename A3>
185 void Call(const tracked_objects::Location& from_here, 213 void Call(const tracked_objects::Location& from_here,
186 void (U::*fn)(A1, A2, A3), 214 void (U::*fn)(A1, A2, A3),
187 typename ParamTraits<A1>::ForwardType a1, 215 typename ParamTraits<A1>::ForwardType a1,
188 typename ParamTraits<A2>::ForwardType a2, 216 typename ParamTraits<A2>::ForwardType a2,
189 typename ParamTraits<A3>::ForwardType a3) const { 217 typename ParamTraits<A3>::ForwardType a3) const {
190 PostOnOwnerThread( 218 PostToOwnerThread(
191 from_here, 219 from_here,
192 Bind(&WeakHandleCore::template DoCall3<U, A1, A2, A3>, 220 Bind(&WeakHandleCore::template DoCall3<U, A1, A2, A3>,
193 this, fn, a1, a2, a3)); 221 this, fn, a1, a2, a3));
194 } 222 }
195 223
196 template <typename U, typename A1, typename A2, typename A3, typename A4> 224 template <typename U, typename A1, typename A2, typename A3, typename A4>
197 void Call(const tracked_objects::Location& from_here, 225 void Call(const tracked_objects::Location& from_here,
198 void (U::*fn)(A1, A2, A3, A4), 226 void (U::*fn)(A1, A2, A3, A4),
199 typename ParamTraits<A1>::ForwardType a1, 227 typename ParamTraits<A1>::ForwardType a1,
200 typename ParamTraits<A2>::ForwardType a2, 228 typename ParamTraits<A2>::ForwardType a2,
201 typename ParamTraits<A3>::ForwardType a3, 229 typename ParamTraits<A3>::ForwardType a3,
202 typename ParamTraits<A4>::ForwardType a4) const { 230 typename ParamTraits<A4>::ForwardType a4) const {
203 PostOnOwnerThread( 231 PostToOwnerThread(
204 from_here, 232 from_here,
205 Bind(&WeakHandleCore::template DoCall4<U, A1, A2, A3, A4>, 233 Bind(&WeakHandleCore::template DoCall4<U, A1, A2, A3, A4>,
206 this, fn, a1, a2, a3, a4)); 234 this, fn, a1, a2, a3, a4));
207 } 235 }
208 236
237 protected:
238 // Must be called on |ptr_|'s owner thread exactly once.
239 virtual void CleanupOnOwnerThread() OVERRIDE {
240 CHECK(IsOnOwnerThread());
241 CHECK(ptr_);
242 delete ptr_;
243 ptr_ = NULL;
244 WeakHandleCoreBase::CleanupOnOwnerThread();
245 }
246
209 private: 247 private:
210 friend class base::RefCountedThreadSafe<WeakHandleCore<T> >; 248 // May be called on any thread.
249 ~WeakHandleCore() {
250 // It is safe to read |ptr_| here even if we're not on the owner
251 // thread (see comments on base::AtomicRefCountDecN()).
252 CHECK(!ptr_);
253 }
211 254
212 // GCC 4.2.1 on OS X gets confused if all the DoCall functions are 255 // GCC 4.2.1 on OS X gets confused if all the DoCall functions are
213 // named the same, so we distinguish them. 256 // named the same, so we distinguish them.
214 257
215 template <typename U> 258 template <typename U>
216 void DoCall0(void (U::*fn)(void)) const { 259 void DoCall0(void (U::*fn)(void)) const {
217 CHECK(IsOnOwnerThread()); 260 CHECK(IsOnOwnerThread());
218 if (!ptr_->get()) { 261 if (!Get()) {
219 return; 262 return;
220 } 263 }
221 (ptr_->get()->*fn)(); 264 (Get()->*fn)();
222 } 265 }
223 266
224 template <typename U, typename A1> 267 template <typename U, typename A1>
225 void DoCall1(void (U::*fn)(A1), 268 void DoCall1(void (U::*fn)(A1),
226 typename ParamTraits<A1>::ForwardType a1) const { 269 typename ParamTraits<A1>::ForwardType a1) const {
227 CHECK(IsOnOwnerThread()); 270 CHECK(IsOnOwnerThread());
228 if (!ptr_->get()) { 271 if (!Get()) {
229 return; 272 return;
230 } 273 }
231 (ptr_->get()->*fn)(a1); 274 (Get()->*fn)(a1);
232 } 275 }
233 276
234 template <typename U, typename A1, typename A2> 277 template <typename U, typename A1, typename A2>
235 void DoCall2(void (U::*fn)(A1, A2), 278 void DoCall2(void (U::*fn)(A1, A2),
236 typename ParamTraits<A1>::ForwardType a1, 279 typename ParamTraits<A1>::ForwardType a1,
237 typename ParamTraits<A2>::ForwardType a2) const { 280 typename ParamTraits<A2>::ForwardType a2) const {
238 CHECK(IsOnOwnerThread()); 281 CHECK(IsOnOwnerThread());
239 if (!ptr_->get()) { 282 if (!Get()) {
240 return; 283 return;
241 } 284 }
242 (ptr_->get()->*fn)(a1, a2); 285 (Get()->*fn)(a1, a2);
243 } 286 }
244 287
245 template <typename U, typename A1, typename A2, typename A3> 288 template <typename U, typename A1, typename A2, typename A3>
246 void DoCall3(void (U::*fn)(A1, A2, A3), 289 void DoCall3(void (U::*fn)(A1, A2, A3),
247 typename ParamTraits<A1>::ForwardType a1, 290 typename ParamTraits<A1>::ForwardType a1,
248 typename ParamTraits<A2>::ForwardType a2, 291 typename ParamTraits<A2>::ForwardType a2,
249 typename ParamTraits<A3>::ForwardType a3) const { 292 typename ParamTraits<A3>::ForwardType a3) const {
250 CHECK(IsOnOwnerThread()); 293 CHECK(IsOnOwnerThread());
251 if (!ptr_->get()) { 294 if (!Get()) {
252 return; 295 return;
253 } 296 }
254 (ptr_->get()->*fn)(a1, a2, a3); 297 (Get()->*fn)(a1, a2, a3);
255 } 298 }
256 299
257 template <typename U, typename A1, typename A2, typename A3, typename A4> 300 template <typename U, typename A1, typename A2, typename A3, typename A4>
258 void DoCall4(void (U::*fn)(A1, A2, A3, A4), 301 void DoCall4(void (U::*fn)(A1, A2, A3, A4),
259 typename ParamTraits<A1>::ForwardType a1, 302 typename ParamTraits<A1>::ForwardType a1,
260 typename ParamTraits<A2>::ForwardType a2, 303 typename ParamTraits<A2>::ForwardType a2,
261 typename ParamTraits<A3>::ForwardType a3, 304 typename ParamTraits<A3>::ForwardType a3,
262 typename ParamTraits<A4>::ForwardType a4) const { 305 typename ParamTraits<A4>::ForwardType a4) const {
263 CHECK(IsOnOwnerThread()); 306 CHECK(IsOnOwnerThread());
264 if (!ptr_->get()) { 307 if (!Get()) {
265 return; 308 return;
266 } 309 }
267 (ptr_->get()->*fn)(a1, a2, a3, a4); 310 (Get()->*fn)(a1, a2, a3, a4);
268 } 311 }
269 312
270 // Must be used and destroyed only on the owner thread. 313 // Must be dereferenced and destroyed only on the owner thread.
314 // Must be read only on the owner thread or the destructor.
271 base::WeakPtr<T>* ptr_; 315 base::WeakPtr<T>* ptr_;
272 316
273 DISALLOW_COPY_AND_ASSIGN(WeakHandleCore); 317 DISALLOW_COPY_AND_ASSIGN(WeakHandleCore);
274 }; 318 };
275 319
276 } // namespace internal 320 } // namespace internal
277 321
278 // May be destroyed on any thread. 322 // May be destroyed on any thread.
279 // Copying and assignment are welcome. 323 // Copying and assignment are welcome.
280 template <typename T> 324 template <typename T>
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 404
361 // Makes a WeakHandle from a WeakPtr. 405 // Makes a WeakHandle from a WeakPtr.
362 template <typename T> 406 template <typename T>
363 WeakHandle<T> MakeWeakHandle(const base::WeakPtr<T>& ptr) { 407 WeakHandle<T> MakeWeakHandle(const base::WeakPtr<T>& ptr) {
364 return WeakHandle<T>(ptr); 408 return WeakHandle<T>(ptr);
365 } 409 }
366 410
367 } // namespace browser_sync 411 } // namespace browser_sync
368 412
369 #endif // CHROME_BROWSER_SYNC_WEAK_HANDLE_H_ 413 #endif // CHROME_BROWSER_SYNC_WEAK_HANDLE_H_
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/sync/weak_handle.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698