Chromium Code Reviews| 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 |