blob: 85a26d162c80003a7bc6bd588eafe05bd9fb588d [file] [log] [blame]
[email protected]3125d6462009-09-01 20:50:171// 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//
[email protected]5fb6e15d2009-12-15 20:48:0319// class Controller : public SupportsWeakPtr<Controller> {
[email protected]3125d6462009-09-01 20:50:1720// public:
[email protected]5fb6e15d2009-12-15 20:48:0321// void SpawnWorker() { Worker::StartNew(AsWeakPtr()); }
[email protected]3125d6462009-09-01 20:50:1722// 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
58namespace base {
59
60namespace internal {
61// These classes are part of the WeakPtr implementation.
62// DO NOT USE THESE CLASSES DIRECTLY YOURSELF.
63
64class WeakReference {
65 public:
[email protected]59326aac2009-09-25 23:34:3466 class Flag : public RefCounted<Flag>, public NonThreadSafe {
[email protected]d52e97092009-09-17 00:31:0967 public:
[email protected]3a3d47472010-07-15 21:03:5468 Flag(Flag** handle);
69 ~Flag();
[email protected]59326aac2009-09-25 23:34:3470
[email protected]3a3d47472010-07-15 21:03:5471 void AddRef();
72 void Release();
[email protected]59326aac2009-09-25 23:34:3473 void Invalidate() { handle_ = NULL; }
74 bool is_valid() const { return handle_ != NULL; }
75
76 private:
77 Flag** handle_;
[email protected]3125d6462009-09-01 20:50:1778 };
79
[email protected]3a3d47472010-07-15 21:03:5480 WeakReference();
81 WeakReference(Flag* flag);
[email protected]59326aac2009-09-25 23:34:3482
[email protected]3a3d47472010-07-15 21:03:5483 bool is_valid() const;
[email protected]59326aac2009-09-25 23:34:3484
85 private:
[email protected]3125d6462009-09-01 20:50:1786 scoped_refptr<Flag> flag_;
87};
88
89class WeakReferenceOwner {
90 public:
[email protected]3a3d47472010-07-15 21:03:5491 WeakReferenceOwner();
92 ~WeakReferenceOwner();
[email protected]59326aac2009-09-25 23:34:3493
[email protected]3a3d47472010-07-15 21:03:5494 WeakReference GetRef() const;
[email protected]3125d6462009-09-01 20:50:1795
[email protected]59326aac2009-09-25 23:34:3496 bool HasRefs() const {
97 return flag_ != NULL;
98 }
99
[email protected]3a3d47472010-07-15 21:03:54100 void Invalidate();
[email protected]3125d6462009-09-01 20:50:17101
102 private:
[email protected]59326aac2009-09-25 23:34:34103 mutable WeakReference::Flag* flag_;
[email protected]3125d6462009-09-01 20:50:17104};
105
106// This class simplifies the implementation of WeakPtr's type conversion
107// constructor by avoiding the need for a public accessor for ref_. A
108// WeakPtr<T> cannot access the private members of WeakPtr<U>, so this
109// base class gives us a way to access ref_ in a protected fashion.
110class WeakPtrBase {
111 public:
[email protected]3a3d47472010-07-15 21:03:54112 WeakPtrBase();
[email protected]3125d6462009-09-01 20:50:17113
114 protected:
[email protected]3a3d47472010-07-15 21:03:54115 WeakPtrBase(const WeakReference& ref);
[email protected]3125d6462009-09-01 20:50:17116
117 WeakReference ref_;
118};
119
120} // namespace internal
121
122template <typename T> class SupportsWeakPtr;
123template <typename T> class WeakPtrFactory;
124
125// The WeakPtr class holds a weak reference to |T*|.
126//
127// This class is designed to be used like a normal pointer. You should always
128// null-test an object of this class before using it or invoking a method that
129// may result in the underlying object being destroyed.
130//
131// EXAMPLE:
132//
133// class Foo { ... };
134// WeakPtr<Foo> foo;
135// if (foo)
136// foo->method();
137//
138template <typename T>
139class WeakPtr : public internal::WeakPtrBase {
140 public:
141 WeakPtr() : ptr_(NULL) {
142 }
143
144 // Allow conversion from U to T provided U "is a" T.
145 template <typename U>
146 WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.get()) {
147 }
148
149 T* get() const { return ref_.is_valid() ? ptr_ : NULL; }
150 operator T*() const { return get(); }
151
152 T* operator*() const {
153 DCHECK(get() != NULL);
154 return *get();
155 }
156 T* operator->() const {
157 DCHECK(get() != NULL);
158 return get();
159 }
160
[email protected]f103ab72009-09-02 17:10:59161 void reset() {
162 ref_ = internal::WeakReference();
163 ptr_ = NULL;
164 }
165
[email protected]3125d6462009-09-01 20:50:17166 private:
167 friend class SupportsWeakPtr<T>;
168 friend class WeakPtrFactory<T>;
169
170 WeakPtr(const internal::WeakReference& ref, T* ptr)
171 : WeakPtrBase(ref), ptr_(ptr) {
172 }
173
174 // This pointer is only valid when ref_.is_valid() is true. Otherwise, its
175 // value is undefined (as opposed to NULL).
176 T* ptr_;
177};
178
179// A class may extend from SupportsWeakPtr to expose weak pointers to itself.
180// This is useful in cases where you want others to be able to get a weak
181// pointer to your class. It also has the property that you don't need to
182// initialize it from your constructor.
183template <class T>
184class SupportsWeakPtr {
185 public:
186 SupportsWeakPtr() {}
187
188 WeakPtr<T> AsWeakPtr() {
189 return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this));
190 }
191
192 private:
193 internal::WeakReferenceOwner weak_reference_owner_;
194 DISALLOW_COPY_AND_ASSIGN(SupportsWeakPtr);
195};
196
197// A class may alternatively be composed of a WeakPtrFactory and thereby
198// control how it exposes weak pointers to itself. This is helpful if you only
199// need weak pointers within the implementation of a class. This class is also
200// useful when working with primitive types. For example, you could have a
201// WeakPtrFactory<bool> that is used to pass around a weak reference to a bool.
202template <class T>
203class WeakPtrFactory {
204 public:
205 explicit WeakPtrFactory(T* ptr) : ptr_(ptr) {
206 }
207
208 WeakPtr<T> GetWeakPtr() {
209 return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_);
210 }
211
212 // Call this method to invalidate all existing weak pointers.
[email protected]59326aac2009-09-25 23:34:34213 void InvalidateWeakPtrs() {
214 weak_reference_owner_.Invalidate();
215 }
216
217 // Call this method to determine if any weak pointers exist.
218 bool HasWeakPtrs() const {
219 return weak_reference_owner_.HasRefs();
220 }
[email protected]3125d6462009-09-01 20:50:17221
222 private:
223 internal::WeakReferenceOwner weak_reference_owner_;
224 T* ptr_;
225 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory);
226};
227
228} // namespace base
229
230#endif // BASE_WEAK_PTR_H_