Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: base/memory/weak_ptr.h

Issue 7677028: Make WeakPtr thread-safe, i.e. allow cross-thread copying of WeakPtr (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add suppression Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | base/memory/weak_ptr.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 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 //
10 // A common alternative to weak pointers is to have the shared object hold a 19 // A common alternative to weak pointers is to have the shared object hold a
11 // list of all referrers, and then when the shared object is destroyed, it 20 // list of all referrers, and then when the shared object is destroyed, it
12 // calls a method on the referrers to tell them to drop their references. This 21 // calls a method on the referrers to tell them to drop their references. This
13 // approach also requires the referrers to tell the shared object when they get 22 // approach also requires the referrers to tell the shared object when they get
14 // destroyed so that the shared object can remove the referrer from its list of 23 // destroyed so that the shared object can remove the referrer from its list of
15 // referrers. Such a solution works, but it is a bit complex. 24 // referrers. Such a solution works, but it is a bit complex.
16 // 25 //
17 // EXAMPLE: 26 // EXAMPLE:
18 // 27 //
19 // class Controller : public SupportsWeakPtr<Controller> { 28 // class Controller : public SupportsWeakPtr<Controller> {
(...skipping 18 matching lines...) Expand all
38 // WeakPtr<Controller> controller_; 47 // WeakPtr<Controller> controller_;
39 // }; 48 // };
40 // 49 //
41 // Given the above classes, a consumer may allocate a Controller object, call 50 // Given the above classes, a consumer may allocate a Controller object, call
42 // SpawnWorker several times, and then destroy the Controller object before all 51 // SpawnWorker several times, and then destroy the Controller object before all
43 // of the workers have completed. Because the Worker class only holds a weak 52 // of the workers have completed. Because the Worker class only holds a weak
44 // pointer to the Controller, we don't have to worry about the Worker 53 // pointer to the Controller, we don't have to worry about the Worker
45 // dereferencing the Controller back pointer after the Controller has been 54 // dereferencing the Controller back pointer after the Controller has been
46 // destroyed. 55 // destroyed.
47 // 56 //
48 // WARNING: weak pointers are not threadsafe!!! You must only use a WeakPtr
49 // instance on thread where it was created.
50 57
51 #ifndef BASE_MEMORY_WEAK_PTR_H_ 58 #ifndef BASE_MEMORY_WEAK_PTR_H_
52 #define BASE_MEMORY_WEAK_PTR_H_ 59 #define BASE_MEMORY_WEAK_PTR_H_
53 #pragma once 60 #pragma once
54 61
55 #include "base/base_export.h" 62 #include "base/base_export.h"
56 #include "base/logging.h" 63 #include "base/logging.h"
57 #include "base/memory/ref_counted.h" 64 #include "base/memory/ref_counted.h"
58 #include "base/threading/thread_checker.h" 65 #include "base/threading/thread_checker.h"
59 66
60 namespace base { 67 namespace base {
61 68
62 namespace internal { 69 namespace internal {
63 // These classes are part of the WeakPtr implementation. 70 // These classes are part of the WeakPtr implementation.
64 // DO NOT USE THESE CLASSES DIRECTLY YOURSELF. 71 // DO NOT USE THESE CLASSES DIRECTLY YOURSELF.
65 72
66 class BASE_EXPORT WeakReference { 73 class BASE_EXPORT WeakReference {
67 public: 74 public:
68 // While Flag is bound to a specific thread, it may be deleted from another 75 // While Flag is bound to a specific thread, it may be deleted from another
69 // via base::WeakPtr::~WeakPtr(). 76 // via base::WeakPtr::~WeakPtr().
70 class Flag : public RefCountedThreadSafe<Flag> { 77 class Flag : public RefCountedThreadSafe<Flag> {
71 public: 78 public:
72 explicit Flag(Flag** handle); 79 Flag();
73 80
74 void Invalidate(); 81 void Invalidate();
75 bool IsValid() const; 82 bool IsValid() const;
76 83
77 void DetachFromThread() { thread_checker_.DetachFromThread(); } 84 void DetachFromThread() { thread_checker_.DetachFromThread(); }
78 85
79 private: 86 private:
80 friend class base::RefCountedThreadSafe<Flag>; 87 friend class base::RefCountedThreadSafe<Flag>;
81 88
82 ~Flag(); 89 ~Flag();
83 90
84 ThreadChecker thread_checker_; 91 ThreadChecker thread_checker_;
85 Flag** handle_; 92 bool is_valid_;
86 }; 93 };
87 94
88 WeakReference(); 95 WeakReference();
89 WeakReference(Flag* flag); 96 explicit WeakReference(const Flag* flag);
90 ~WeakReference(); 97 ~WeakReference();
91 98
92 bool is_valid() const; 99 bool is_valid() const;
93 100
94 private: 101 private:
95 scoped_refptr<Flag> flag_; 102 scoped_refptr<const Flag> flag_;
96 }; 103 };
97 104
98 class BASE_EXPORT WeakReferenceOwner { 105 class BASE_EXPORT WeakReferenceOwner {
99 public: 106 public:
100 WeakReferenceOwner(); 107 WeakReferenceOwner();
101 ~WeakReferenceOwner(); 108 ~WeakReferenceOwner();
102 109
103 WeakReference GetRef() const; 110 WeakReference GetRef() const;
104 111
105 bool HasRefs() const { 112 bool HasRefs() const {
106 return flag_ != NULL; 113 return flag_.get() && !flag_->HasOneRef();
107 } 114 }
108 115
109 void Invalidate(); 116 void Invalidate();
110 117
111 // Indicates that this object will be used on another thread from now on. 118 // Indicates that this object will be used on another thread from now on.
112 void DetachFromThread() { 119 void DetachFromThread() {
113 if (flag_) flag_->DetachFromThread(); 120 if (flag_) flag_->DetachFromThread();
114 } 121 }
115 122
116 private: 123 private:
117 mutable WeakReference::Flag* flag_; 124 mutable scoped_refptr<WeakReference::Flag> flag_;
118 }; 125 };
119 126
120 // This class simplifies the implementation of WeakPtr's type conversion 127 // This class simplifies the implementation of WeakPtr's type conversion
121 // constructor by avoiding the need for a public accessor for ref_. A 128 // constructor by avoiding the need for a public accessor for ref_. A
122 // WeakPtr<T> cannot access the private members of WeakPtr<U>, so this 129 // WeakPtr<T> cannot access the private members of WeakPtr<U>, so this
123 // base class gives us a way to access ref_ in a protected fashion. 130 // base class gives us a way to access ref_ in a protected fashion.
124 class BASE_EXPORT WeakPtrBase { 131 class BASE_EXPORT WeakPtrBase {
125 public: 132 public:
126 WeakPtrBase(); 133 WeakPtrBase();
127 ~WeakPtrBase(); 134 ~WeakPtrBase();
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 253
247 private: 254 private:
248 internal::WeakReferenceOwner weak_reference_owner_; 255 internal::WeakReferenceOwner weak_reference_owner_;
249 T* ptr_; 256 T* ptr_;
250 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory); 257 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory);
251 }; 258 };
252 259
253 } // namespace base 260 } // namespace base
254 261
255 #endif // BASE_MEMORY_WEAK_PTR_H_ 262 #endif // BASE_MEMORY_WEAK_PTR_H_
OLDNEW
« no previous file with comments | « no previous file | base/memory/weak_ptr.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698