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

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: 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') | chrome/browser/sync/weak_handle.cc » ('J')
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. If you override this, make to still call
Nicolas Zea 2011/08/04 19:54:10 "make sure to still"
akalin 2011/08/04 21:56:53 Rendered moot.
132 // WeakHandleCoreBase::DestroyOnOwnerThread());
133 virtual void DestroyOnOwnerThread();
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 this object.
144 void DestroyAndDelete();
Nicolas Zea 2011/08/04 19:54:10 I find the difference between "destroy" and "delet
akalin 2011/08/04 21:56:53 Good point. Renamed 'Destroy' to 'Cleanup' and 'D
145
146 // Calls DestroyOnOwnerThread() and deletes |this|. Must be called
147 // on the owner thread via DestroyAndDelete().
148 void DestroyAndDeleteOnOwnerThread();
149
150 // May be read on any thread, but should only be dereferenced on the
151 // owner thread.
152 MessageLoop* const owner_loop_;
153
154 // May be used on any thread.
155 const scoped_refptr<base::MessageLoopProxy> owner_loop_proxy_;
156
157 // Should only be read on the owner thread or in the destructor.
158 bool destroyed_on_owner_thread_;
Nicolas Zea 2011/08/04 19:54:10 Is this variable just used for the purpose of CHEC
akalin 2011/08/04 21:56:53 Yes. I think it's still worth having, though.
126 159
127 DISALLOW_COPY_AND_ASSIGN(WeakHandleCoreBase); 160 DISALLOW_COPY_AND_ASSIGN(WeakHandleCoreBase);
128 }; 161 };
129 162
130 // WeakHandleCore<T> contains all the logic for WeakHandle<T>. 163 // WeakHandleCore<T> contains all the logic for WeakHandle<T>.
131 template <typename T> 164 template <typename T>
132 class WeakHandleCore 165 class WeakHandleCore : public WeakHandleCoreBase {
133 : public WeakHandleCoreBase,
134 public base::RefCountedThreadSafe<WeakHandleCore<T> > {
135 public: 166 public:
136 // Must be called on |ptr|'s owner thread, which is assumed to be 167 // Must be called on |ptr|'s owner thread, which is assumed to be
137 // the current thread. 168 // the current thread.
138 explicit WeakHandleCore(const base::WeakPtr<T>& ptr) 169 explicit WeakHandleCore(const base::WeakPtr<T>& ptr)
139 : ptr_(new base::WeakPtr<T>(ptr)) {} 170 : ptr_(new base::WeakPtr<T>(ptr)) {}
140 171
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. 172 // Must be called on |ptr_|'s owner thread.
147 const base::WeakPtr<T>& Get() const { 173 base::WeakPtr<T> Get() const {
148 CHECK(IsOnOwnerThread()); 174 CHECK(IsOnOwnerThread());
149 return *ptr_; 175 return ptr_ ? *ptr_ : base::WeakPtr<T>();
150 } 176 }
151 177
152 // Call(...) may be called on any thread, but all its arguments 178 // Call(...) may be called on any thread, but all its arguments
153 // should be safe to be bound and copied across threads. 179 // should be safe to be bound and copied across threads.
154 180
155 template <typename U> 181 template <typename U>
156 void Call(const tracked_objects::Location& from_here, 182 void Call(const tracked_objects::Location& from_here,
157 void (U::*fn)(void)) const { 183 void (U::*fn)(void)) const {
158 PostOnOwnerThread( 184 PostToOwnerThread(
159 from_here, 185 from_here,
160 Bind(&WeakHandleCore::template DoCall0<U>, this, fn)); 186 Bind(&WeakHandleCore::template DoCall0<U>, this, fn));
161 } 187 }
162 188
163 template <typename U, typename A1> 189 template <typename U, typename A1>
164 void Call(const tracked_objects::Location& from_here, 190 void Call(const tracked_objects::Location& from_here,
165 void (U::*fn)(A1), 191 void (U::*fn)(A1),
166 typename ParamTraits<A1>::ForwardType a1) const { 192 typename ParamTraits<A1>::ForwardType a1) const {
167 PostOnOwnerThread( 193 PostToOwnerThread(
168 from_here, 194 from_here,
169 Bind(&WeakHandleCore::template DoCall1<U, A1>, 195 Bind(&WeakHandleCore::template DoCall1<U, A1>,
170 this, fn, a1)); 196 this, fn, a1));
171 } 197 }
172 198
173 template <typename U, typename A1, typename A2> 199 template <typename U, typename A1, typename A2>
174 void Call(const tracked_objects::Location& from_here, 200 void Call(const tracked_objects::Location& from_here,
175 void (U::*fn)(A1, A2), 201 void (U::*fn)(A1, A2),
176 typename ParamTraits<A1>::ForwardType a1, 202 typename ParamTraits<A1>::ForwardType a1,
177 typename ParamTraits<A2>::ForwardType a2) const { 203 typename ParamTraits<A2>::ForwardType a2) const {
178 PostOnOwnerThread( 204 PostToOwnerThread(
179 from_here, 205 from_here,
180 Bind(&WeakHandleCore::template DoCall2<U, A1, A2>, 206 Bind(&WeakHandleCore::template DoCall2<U, A1, A2>,
181 this, fn, a1, a2)); 207 this, fn, a1, a2));
182 } 208 }
183 209
184 template <typename U, typename A1, typename A2, typename A3> 210 template <typename U, typename A1, typename A2, typename A3>
185 void Call(const tracked_objects::Location& from_here, 211 void Call(const tracked_objects::Location& from_here,
186 void (U::*fn)(A1, A2, A3), 212 void (U::*fn)(A1, A2, A3),
187 typename ParamTraits<A1>::ForwardType a1, 213 typename ParamTraits<A1>::ForwardType a1,
188 typename ParamTraits<A2>::ForwardType a2, 214 typename ParamTraits<A2>::ForwardType a2,
189 typename ParamTraits<A3>::ForwardType a3) const { 215 typename ParamTraits<A3>::ForwardType a3) const {
190 PostOnOwnerThread( 216 PostToOwnerThread(
191 from_here, 217 from_here,
192 Bind(&WeakHandleCore::template DoCall3<U, A1, A2, A3>, 218 Bind(&WeakHandleCore::template DoCall3<U, A1, A2, A3>,
193 this, fn, a1, a2, a3)); 219 this, fn, a1, a2, a3));
194 } 220 }
195 221
196 template <typename U, typename A1, typename A2, typename A3, typename A4> 222 template <typename U, typename A1, typename A2, typename A3, typename A4>
197 void Call(const tracked_objects::Location& from_here, 223 void Call(const tracked_objects::Location& from_here,
198 void (U::*fn)(A1, A2, A3, A4), 224 void (U::*fn)(A1, A2, A3, A4),
199 typename ParamTraits<A1>::ForwardType a1, 225 typename ParamTraits<A1>::ForwardType a1,
200 typename ParamTraits<A2>::ForwardType a2, 226 typename ParamTraits<A2>::ForwardType a2,
201 typename ParamTraits<A3>::ForwardType a3, 227 typename ParamTraits<A3>::ForwardType a3,
202 typename ParamTraits<A4>::ForwardType a4) const { 228 typename ParamTraits<A4>::ForwardType a4) const {
203 PostOnOwnerThread( 229 PostToOwnerThread(
204 from_here, 230 from_here,
205 Bind(&WeakHandleCore::template DoCall4<U, A1, A2, A3, A4>, 231 Bind(&WeakHandleCore::template DoCall4<U, A1, A2, A3, A4>,
206 this, fn, a1, a2, a3, a4)); 232 this, fn, a1, a2, a3, a4));
207 } 233 }
208 234
235 protected:
236 // Must be called on |ptr_|'s owner thread exactly once.
237 virtual void DestroyOnOwnerThread() OVERRIDE {
238 CHECK(IsOnOwnerThread());
239 CHECK(ptr_);
240 delete ptr_;
241 ptr_ = NULL;
242 WeakHandleCoreBase::DestroyOnOwnerThread();
243 }
244
209 private: 245 private:
210 friend class base::RefCountedThreadSafe<WeakHandleCore<T> >; 246 // May be called on any thread.
247 ~WeakHandleCore() {
248 // It is safe to read |ptr_| here even if we're not on the owner
249 // thread (see comments on base::AtomicRefCountDecN()).
250 CHECK(!ptr_);
251 }
211 252
212 // GCC 4.2.1 on OS X gets confused if all the DoCall functions are 253 // GCC 4.2.1 on OS X gets confused if all the DoCall functions are
213 // named the same, so we distinguish them. 254 // named the same, so we distinguish them.
214 255
215 template <typename U> 256 template <typename U>
216 void DoCall0(void (U::*fn)(void)) const { 257 void DoCall0(void (U::*fn)(void)) const {
217 CHECK(IsOnOwnerThread()); 258 CHECK(IsOnOwnerThread());
218 if (!ptr_->get()) { 259 if (!Get().get()) {
Nicolas Zea 2011/08/04 19:54:10 :( Maybe Get() can be changed to GetScopedPtr()?
akalin 2011/08/04 21:56:53 WeakPtr<T> can be cast to T*, so just changed to G
219 return; 260 return;
220 } 261 }
221 (ptr_->get()->*fn)(); 262 (Get()->*fn)();
222 } 263 }
223 264
224 template <typename U, typename A1> 265 template <typename U, typename A1>
225 void DoCall1(void (U::*fn)(A1), 266 void DoCall1(void (U::*fn)(A1),
226 typename ParamTraits<A1>::ForwardType a1) const { 267 typename ParamTraits<A1>::ForwardType a1) const {
227 CHECK(IsOnOwnerThread()); 268 CHECK(IsOnOwnerThread());
228 if (!ptr_->get()) { 269 if (!Get().get()) {
229 return; 270 return;
230 } 271 }
231 (ptr_->get()->*fn)(a1); 272 (Get()->*fn)(a1);
232 } 273 }
233 274
234 template <typename U, typename A1, typename A2> 275 template <typename U, typename A1, typename A2>
235 void DoCall2(void (U::*fn)(A1, A2), 276 void DoCall2(void (U::*fn)(A1, A2),
236 typename ParamTraits<A1>::ForwardType a1, 277 typename ParamTraits<A1>::ForwardType a1,
237 typename ParamTraits<A2>::ForwardType a2) const { 278 typename ParamTraits<A2>::ForwardType a2) const {
238 CHECK(IsOnOwnerThread()); 279 CHECK(IsOnOwnerThread());
239 if (!ptr_->get()) { 280 if (!Get().get()) {
240 return; 281 return;
241 } 282 }
242 (ptr_->get()->*fn)(a1, a2); 283 (Get()->*fn)(a1, a2);
243 } 284 }
244 285
245 template <typename U, typename A1, typename A2, typename A3> 286 template <typename U, typename A1, typename A2, typename A3>
246 void DoCall3(void (U::*fn)(A1, A2, A3), 287 void DoCall3(void (U::*fn)(A1, A2, A3),
247 typename ParamTraits<A1>::ForwardType a1, 288 typename ParamTraits<A1>::ForwardType a1,
248 typename ParamTraits<A2>::ForwardType a2, 289 typename ParamTraits<A2>::ForwardType a2,
249 typename ParamTraits<A3>::ForwardType a3) const { 290 typename ParamTraits<A3>::ForwardType a3) const {
250 CHECK(IsOnOwnerThread()); 291 CHECK(IsOnOwnerThread());
251 if (!ptr_->get()) { 292 if (!Get().get()) {
252 return; 293 return;
253 } 294 }
254 (ptr_->get()->*fn)(a1, a2, a3); 295 (Get()->*fn)(a1, a2, a3);
255 } 296 }
256 297
257 template <typename U, typename A1, typename A2, typename A3, typename A4> 298 template <typename U, typename A1, typename A2, typename A3, typename A4>
258 void DoCall4(void (U::*fn)(A1, A2, A3, A4), 299 void DoCall4(void (U::*fn)(A1, A2, A3, A4),
259 typename ParamTraits<A1>::ForwardType a1, 300 typename ParamTraits<A1>::ForwardType a1,
260 typename ParamTraits<A2>::ForwardType a2, 301 typename ParamTraits<A2>::ForwardType a2,
261 typename ParamTraits<A3>::ForwardType a3, 302 typename ParamTraits<A3>::ForwardType a3,
262 typename ParamTraits<A4>::ForwardType a4) const { 303 typename ParamTraits<A4>::ForwardType a4) const {
263 CHECK(IsOnOwnerThread()); 304 CHECK(IsOnOwnerThread());
264 if (!ptr_->get()) { 305 if (!Get().get()) {
265 return; 306 return;
266 } 307 }
267 (ptr_->get()->*fn)(a1, a2, a3, a4); 308 (Get()->*fn)(a1, a2, a3, a4);
268 } 309 }
269 310
270 // Must be used and destroyed only on the owner thread. 311 // Must be dereferenced and destroyed only on the owner thread.
312 // Must be read only on the owner thread or the destructor.
271 base::WeakPtr<T>* ptr_; 313 base::WeakPtr<T>* ptr_;
272 314
273 DISALLOW_COPY_AND_ASSIGN(WeakHandleCore); 315 DISALLOW_COPY_AND_ASSIGN(WeakHandleCore);
274 }; 316 };
275 317
276 } // namespace internal 318 } // namespace internal
277 319
278 // May be destroyed on any thread. 320 // May be destroyed on any thread.
279 // Copying and assignment are welcome. 321 // Copying and assignment are welcome.
280 template <typename T> 322 template <typename T>
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 402
361 // Makes a WeakHandle from a WeakPtr. 403 // Makes a WeakHandle from a WeakPtr.
362 template <typename T> 404 template <typename T>
363 WeakHandle<T> MakeWeakHandle(const base::WeakPtr<T>& ptr) { 405 WeakHandle<T> MakeWeakHandle(const base::WeakPtr<T>& ptr) {
364 return WeakHandle<T>(ptr); 406 return WeakHandle<T>(ptr);
365 } 407 }
366 408
367 } // namespace browser_sync 409 } // namespace browser_sync
368 410
369 #endif // CHROME_BROWSER_SYNC_WEAK_HANDLE_H_ 411 #endif // CHROME_BROWSER_SYNC_WEAK_HANDLE_H_
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/sync/weak_handle.cc » ('j') | chrome/browser/sync/weak_handle.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698