| 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 |