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

Side by Side Diff: base/weak_ptr.h

Issue 183026: Add a WeakPtr<T> class.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 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 | « base/base.gyp ('k') | base/weak_ptr_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
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
7 // bound to the lifetime of the referrers. In other words, this is useful when
8 // reference counting is not a good fit.
9 //
10 // 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
12 // 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
14 // 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.
16 //
17 // EXAMPLE:
18 //
19 // class Controller : public SupportsWeakPtr {
20 // public:
21 // void SpawnWorker() { Worker::StartNew(GetWeakPtr()); }
22 // void WorkComplete(const Result& result) { ... }
23 // };
24 //
25 // class Worker {
26 // public:
27 // static void StartNew(const WeakPtr<Controller>& controller) {
28 // Worker* worker = new Worker(controller);
29 // // Kick off asynchronous processing...
30 // }
31 // private:
32 // Worker(const WeakPtr<Controller>& controller)
33 // : controller_(controller) {}
34 // void DidCompleteAsynchronousProcessing(const Result& result) {
35 // if (controller_)
36 // controller_->WorkComplete(result);
37 // }
38 // WeakPtr<Controller> controller_;
39 // };
40 //
41 // Given the above classes, a consumer may allocate a Controller object, call
42 // 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
44 // pointer to the Controller, we don't have to worry about the Worker
45 // dereferencing the Controller back pointer after the Controller has been
46 // destroyed.
47 //
48 // WARNING: weak pointers are not threadsafe!!! You must only use a WeakPtr
49 // instance on thread where it was created.
50
51 #ifndef BASE_WEAK_PTR_H_
52 #define BASE_WEAK_PTR_H_
53
54 #include "base/logging.h"
55 #include "base/non_thread_safe.h"
56 #include "base/ref_counted.h"
57
58 namespace base {
59
60 namespace internal {
61 // These classes are part of the WeakPtr implementation.
62 // DO NOT USE THESE CLASSES DIRECTLY YOURSELF.
63
64 class WeakReference {
65 public:
66 void EnsureInitialized() {
67 // Lazy initialization helps faciliate the NonThreadSafe debug checks.
68 if (!flag_) {
69 flag_ = new Flag();
70 flag_->data = true;
71 }
72 }
73
74 void Invalidate() {
75 if (flag_)
76 flag_->data = false;
77 }
78
79 bool is_valid() const { return flag_ && flag_->data; }
80
81 private:
82 // A reference counted boolean that is true when the weak reference is valid
83 // and false otherwise.
84 class Flag : public RefCountedData<bool>, public NonThreadSafe {
85 };
86
87 scoped_refptr<Flag> flag_;
88 };
89
90 class WeakReferenceOwner {
91 public:
92 ~WeakReferenceOwner() {
93 ref_.Invalidate();
94 }
95
96 const WeakReference& GetRef() const {
97 ref_.EnsureInitialized();
98 return ref_;
99 }
100
101 void Invalidate() { ref_.Invalidate(); }
102
103 private:
104 mutable WeakReference ref_;
105 };
106
107 // This class simplifies the implementation of WeakPtr's type conversion
108 // constructor by avoiding the need for a public accessor for ref_. A
109 // WeakPtr<T> cannot access the private members of WeakPtr<U>, so this
110 // base class gives us a way to access ref_ in a protected fashion.
111 class WeakPtrBase {
112 public:
113 WeakPtrBase() {
114 }
115
116 protected:
117 WeakPtrBase(const WeakReference& ref) : ref_(ref) {
118 }
119
120 WeakReference ref_;
121 };
122
123 } // namespace internal
124
125 template <typename T> class SupportsWeakPtr;
126 template <typename T> class WeakPtrFactory;
127
128 // The WeakPtr class holds a weak reference to |T*|.
129 //
130 // This class is designed to be used like a normal pointer. You should always
131 // null-test an object of this class before using it or invoking a method that
132 // may result in the underlying object being destroyed.
133 //
134 // EXAMPLE:
135 //
136 // class Foo { ... };
137 // WeakPtr<Foo> foo;
138 // if (foo)
139 // foo->method();
140 //
141 template <typename T>
142 class WeakPtr : public internal::WeakPtrBase {
143 public:
144 WeakPtr() : ptr_(NULL) {
145 }
146
147 // Allow conversion from U to T provided U "is a" T.
148 template <typename U>
149 WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.get()) {
150 }
151
152 T* get() const { return ref_.is_valid() ? ptr_ : NULL; }
153 operator T*() const { return get(); }
154
155 T* operator*() const {
156 DCHECK(get() != NULL);
157 return *get();
158 }
159 T* operator->() const {
160 DCHECK(get() != NULL);
161 return get();
162 }
163
164 private:
165 friend class SupportsWeakPtr<T>;
166 friend class WeakPtrFactory<T>;
167
168 WeakPtr(const internal::WeakReference& ref, T* ptr)
169 : WeakPtrBase(ref), ptr_(ptr) {
170 }
171
172 // This pointer is only valid when ref_.is_valid() is true. Otherwise, its
173 // value is undefined (as opposed to NULL).
174 T* ptr_;
175 };
176
177 // A class may extend from SupportsWeakPtr to expose weak pointers to itself.
178 // This is useful in cases where you want others to be able to get a weak
179 // pointer to your class. It also has the property that you don't need to
180 // initialize it from your constructor.
181 template <class T>
182 class SupportsWeakPtr {
183 public:
184 SupportsWeakPtr() {}
185
186 WeakPtr<T> AsWeakPtr() {
187 return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this));
188 }
189
190 private:
191 internal::WeakReferenceOwner weak_reference_owner_;
192 DISALLOW_COPY_AND_ASSIGN(SupportsWeakPtr);
193 };
194
195 // A class may alternatively be composed of a WeakPtrFactory and thereby
196 // control how it exposes weak pointers to itself. This is helpful if you only
197 // need weak pointers within the implementation of a class. This class is also
198 // useful when working with primitive types. For example, you could have a
199 // WeakPtrFactory<bool> that is used to pass around a weak reference to a bool.
200 template <class T>
201 class WeakPtrFactory {
202 public:
203 explicit WeakPtrFactory(T* ptr) : ptr_(ptr) {
204 }
205
206 WeakPtr<T> GetWeakPtr() {
207 return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_);
208 }
209
210 // Call this method to invalidate all existing weak pointers.
211 void InvalidateWeakPtrs() { weak_reference_owner_.Invalidate(); }
212
213 private:
214 internal::WeakReferenceOwner weak_reference_owner_;
215 T* ptr_;
216 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory);
217 };
218
219 } // namespace base
220
221 #endif // BASE_WEAK_PTR_H_
OLDNEW
« no previous file with comments | « base/base.gyp ('k') | base/weak_ptr_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698