Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 pointers help in cases where you have many objects referring back to a | 5 // Weak pointers help in cases where you have many objects referring back to a |
| 6 // shared object and you wish for the lifetime of the shared object to not be | 6 // shared object and you wish for the lifetime of the shared object to not be |
| 7 // bound to the lifetime of the referrers. In other words, this is useful when | 7 // bound to the lifetime of the referrers. In other words, this is useful when |
| 8 // reference counting is not a good fit. | 8 // reference counting is not a good fit. |
| 9 // | 9 // |
| 10 // Thread-safety notes: | |
| 11 // When you get a WeakPtr (from a WeakPtrFactory or SupportsWeakPtr), | |
| 12 // the WeakPtr becomes bound to the current thread. You may only | |
| 13 // dereference the WeakPtr on that thread. However, it is safe to | |
| 14 // destroy the WeakPtr object on another thread. | |
| 15 // Since a WeakPtr object may be destroyed on a background thread, | |
| 16 // querying WeakPtrFactory's HasWeakPtrs() method can be racy. | |
| 17 // | |
| 18 // | |
| 19 // A common alternative to weak pointers is to have the shared object hold a | 10 // A common alternative to weak pointers is to have the shared object hold a |
| 20 // list of all referrers, and then when the shared object is destroyed, it | 11 // list of all referrers, and then when the shared object is destroyed, it |
| 21 // calls a method on the referrers to tell them to drop their references. This | 12 // calls a method on the referrers to tell them to drop their references. This |
| 22 // approach also requires the referrers to tell the shared object when they get | 13 // approach also requires the referrers to tell the shared object when they get |
| 23 // destroyed so that the shared object can remove the referrer from its list of | 14 // destroyed so that the shared object can remove the referrer from its list of |
| 24 // referrers. Such a solution works, but it is a bit complex. | 15 // referrers. Such a solution works, but it is a bit complex. |
| 25 // | 16 // |
| 26 // EXAMPLE: | 17 // EXAMPLE: |
| 27 // | 18 // |
| 28 // class Controller : public SupportsWeakPtr<Controller> { | 19 // class Controller : public SupportsWeakPtr<Controller> { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 47 // WeakPtr<Controller> controller_; | 38 // WeakPtr<Controller> controller_; |
| 48 // }; | 39 // }; |
| 49 // | 40 // |
| 50 // Given the above classes, a consumer may allocate a Controller object, call | 41 // Given the above classes, a consumer may allocate a Controller object, call |
| 51 // SpawnWorker several times, and then destroy the Controller object before all | 42 // SpawnWorker several times, and then destroy the Controller object before all |
| 52 // of the workers have completed. Because the Worker class only holds a weak | 43 // of the workers have completed. Because the Worker class only holds a weak |
| 53 // pointer to the Controller, we don't have to worry about the Worker | 44 // pointer to the Controller, we don't have to worry about the Worker |
| 54 // dereferencing the Controller back pointer after the Controller has been | 45 // dereferencing the Controller back pointer after the Controller has been |
| 55 // destroyed. | 46 // destroyed. |
| 56 // | 47 // |
| 48 // ------------------------ Thread-safety notes ------------------------ | |
| 49 // When you get a WeakPtr (from a WeakPtrFactory or SupportsWeakPtr), the | |
| 50 // WeakPtr becomes bound to the current thread. You may only dereference the | |
| 51 // WeakPtr on that thread. However, it is safe to destroy the WeakPtr object | |
| 52 // on another thread. Since a WeakPtr object may be destroyed on a background | |
| 53 // thread, querying WeakPtrFactory's HasWeakPtrs() method can be racy. | |
| 54 // | |
| 55 // On the other hand, the object that supports WeakPtr (extends SupportsWeakPtr) | |
| 56 // will be bound to the first thread that creates a WeakPtr pointing to it, | |
| 57 // and can not be deleted from other threads unless all WeakPtrs are deleted. | |
|
Ryan Sleevi
2012/07/10 22:41:54
nit: s/unless/until/
kaiwang
2012/07/11 01:17:05
Done.
| |
| 58 // Calling SupportsWeakPtr::DetachFromThread() can work around this and cancel | |
| 59 // the thread binding, but it's not recommended and unsafe. | |
|
Ryan Sleevi
2012/07/10 22:41:54
I almost wonder if we shouldn't remove DetachFromT
kaiwang
2012/07/11 01:17:05
Searched the code and seems this function is used
| |
| 60 // | |
| 61 // WeakPtrs are usually copied by other threads. Note the copied WeakPtr is | |
|
Ryan Sleevi
2012/07/10 22:41:54
nit: s/are usually/may be/.
nit: drop the "Note"
kaiwang
2012/07/11 01:17:05
Done. Good suggestion :)
| |
| 62 // still bound to original thread, not the thread doing the copy. So the second | |
| 63 // thread can delete the copied WeakPtr but can not dereference it. | |
| 57 | 64 |
| 58 #ifndef BASE_MEMORY_WEAK_PTR_H_ | 65 #ifndef BASE_MEMORY_WEAK_PTR_H_ |
| 59 #define BASE_MEMORY_WEAK_PTR_H_ | 66 #define BASE_MEMORY_WEAK_PTR_H_ |
| 60 #pragma once | 67 #pragma once |
| 61 | 68 |
| 62 #include "base/basictypes.h" | 69 #include "base/basictypes.h" |
| 63 #include "base/base_export.h" | 70 #include "base/base_export.h" |
| 64 #include "base/logging.h" | 71 #include "base/logging.h" |
| 65 #include "base/memory/ref_counted.h" | 72 #include "base/memory/ref_counted.h" |
| 66 #include "base/template_util.h" | 73 #include "base/template_util.h" |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 218 ref_ = internal::WeakReference(); | 225 ref_ = internal::WeakReference(); |
| 219 ptr_ = NULL; | 226 ptr_ = NULL; |
| 220 } | 227 } |
| 221 | 228 |
| 222 private: | 229 private: |
| 223 friend class internal::SupportsWeakPtrBase; | 230 friend class internal::SupportsWeakPtrBase; |
| 224 friend class SupportsWeakPtr<T>; | 231 friend class SupportsWeakPtr<T>; |
| 225 friend class WeakPtrFactory<T>; | 232 friend class WeakPtrFactory<T>; |
| 226 | 233 |
| 227 WeakPtr(const internal::WeakReference& ref, T* ptr) | 234 WeakPtr(const internal::WeakReference& ref, T* ptr) |
| 228 : WeakPtrBase(ref), ptr_(ptr) { | 235 : WeakPtrBase(ref), |
| 236 ptr_(ptr) { | |
| 229 } | 237 } |
| 230 | 238 |
| 231 // This pointer is only valid when ref_.is_valid() is true. Otherwise, its | 239 // This pointer is only valid when ref_.is_valid() is true. Otherwise, its |
| 232 // value is undefined (as opposed to NULL). | 240 // value is undefined (as opposed to NULL). |
| 233 T* ptr_; | 241 T* ptr_; |
| 234 }; | 242 }; |
| 235 | 243 |
| 236 // A class may extend from SupportsWeakPtr to expose weak pointers to itself. | 244 // A class may extend from SupportsWeakPtr to expose weak pointers to itself. |
| 237 // This is useful in cases where you want others to be able to get a weak | 245 // This is useful in cases where you want others to be able to get a weak |
| 238 // pointer to your class. It also has the property that you don't need to | 246 // pointer to your class. It also has the property that you don't need to |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 322 | 330 |
| 323 private: | 331 private: |
| 324 internal::WeakReferenceOwner weak_reference_owner_; | 332 internal::WeakReferenceOwner weak_reference_owner_; |
| 325 T* ptr_; | 333 T* ptr_; |
| 326 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory); | 334 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory); |
| 327 }; | 335 }; |
| 328 | 336 |
| 329 } // namespace base | 337 } // namespace base |
| 330 | 338 |
| 331 #endif // BASE_MEMORY_WEAK_PTR_H_ | 339 #endif // BASE_MEMORY_WEAK_PTR_H_ |
| OLD | NEW |