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