OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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_ |
OLD | NEW |