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 |