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), if it's |
| 50 // the only one pointing to the object, the object become bound to the |
| 51 // current thread, as well as this WeakPtr and all later ones get created. |
| 52 // |
| 53 // You may only dereference the WeakPtr on the thread it binds to. However, it |
| 54 // is safe to destroy the WeakPtr object on another thread. Because of this, |
| 55 // querying WeakPtrFactory's HasWeakPtrs() method can be racy. |
| 56 // |
| 57 // On the other hand, the object that supports WeakPtr (extends SupportsWeakPtr) |
| 58 // can only be deleted from the thread it binds to, until all WeakPtrs are |
| 59 // deleted. |
| 60 // |
| 61 // Calling SupportsWeakPtr::DetachFromThread() can work around the limitations |
| 62 // above and cancel the thread binding of the object and all WeakPtrs pointing |
| 63 // to it, but it's not recommended and unsafe. |
| 64 // |
| 65 // WeakPtrs may be copy-constructed or assigned on threads other than the thread |
| 66 // they are bound to. This does not change the thread binding. So these WeakPtrs |
| 67 // may only be dereferenced on the thread that the original WeakPtr was bound |
| 68 // to. |
57 | 69 |
58 #ifndef BASE_MEMORY_WEAK_PTR_H_ | 70 #ifndef BASE_MEMORY_WEAK_PTR_H_ |
59 #define BASE_MEMORY_WEAK_PTR_H_ | 71 #define BASE_MEMORY_WEAK_PTR_H_ |
60 #pragma once | 72 #pragma once |
61 | 73 |
62 #include "base/basictypes.h" | 74 #include "base/basictypes.h" |
63 #include "base/base_export.h" | 75 #include "base/base_export.h" |
64 #include "base/logging.h" | 76 #include "base/logging.h" |
65 #include "base/memory/ref_counted.h" | 77 #include "base/memory/ref_counted.h" |
66 #include "base/template_util.h" | 78 #include "base/template_util.h" |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 ref_ = internal::WeakReference(); | 230 ref_ = internal::WeakReference(); |
219 ptr_ = NULL; | 231 ptr_ = NULL; |
220 } | 232 } |
221 | 233 |
222 private: | 234 private: |
223 friend class internal::SupportsWeakPtrBase; | 235 friend class internal::SupportsWeakPtrBase; |
224 friend class SupportsWeakPtr<T>; | 236 friend class SupportsWeakPtr<T>; |
225 friend class WeakPtrFactory<T>; | 237 friend class WeakPtrFactory<T>; |
226 | 238 |
227 WeakPtr(const internal::WeakReference& ref, T* ptr) | 239 WeakPtr(const internal::WeakReference& ref, T* ptr) |
228 : WeakPtrBase(ref), ptr_(ptr) { | 240 : WeakPtrBase(ref), |
| 241 ptr_(ptr) { |
229 } | 242 } |
230 | 243 |
231 // This pointer is only valid when ref_.is_valid() is true. Otherwise, its | 244 // This pointer is only valid when ref_.is_valid() is true. Otherwise, its |
232 // value is undefined (as opposed to NULL). | 245 // value is undefined (as opposed to NULL). |
233 T* ptr_; | 246 T* ptr_; |
234 }; | 247 }; |
235 | 248 |
236 // A class may extend from SupportsWeakPtr to expose weak pointers to itself. | 249 // 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 | 250 // 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 | 251 // 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 | 335 |
323 private: | 336 private: |
324 internal::WeakReferenceOwner weak_reference_owner_; | 337 internal::WeakReferenceOwner weak_reference_owner_; |
325 T* ptr_; | 338 T* ptr_; |
326 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory); | 339 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory); |
327 }; | 340 }; |
328 | 341 |
329 } // namespace base | 342 } // namespace base |
330 | 343 |
331 #endif // BASE_MEMORY_WEAK_PTR_H_ | 344 #endif // BASE_MEMORY_WEAK_PTR_H_ |
OLD | NEW |