• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
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<Controller> {
20 //   public:
21 //    void SpawnWorker() { Worker::StartNew(AsWeakPtr()); }
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_MEMORY_WEAK_PTR_H_
52 #define BASE_MEMORY_WEAK_PTR_H_
53 #pragma once
54 
55 #include "base/base_api.h"
56 #include "base/logging.h"
57 #include "base/memory/ref_counted.h"
58 #include "base/threading/thread_checker.h"
59 
60 namespace base {
61 
62 namespace internal {
63 // These classes are part of the WeakPtr implementation.
64 // DO NOT USE THESE CLASSES DIRECTLY YOURSELF.
65 
66 class BASE_API WeakReference {
67  public:
68   // While Flag is bound to a specific thread, it may be deleted from another
69   // via base::WeakPtr::~WeakPtr().
70   class Flag : public RefCountedThreadSafe<Flag> {
71    public:
72     explicit Flag(Flag** handle);
73 
74     void Invalidate();
75     bool IsValid() const;
76 
DetachFromThread()77     void DetachFromThread() { thread_checker_.DetachFromThread(); }
78 
79    private:
80     friend class base::RefCountedThreadSafe<Flag>;
81 
82     ~Flag();
83 
84     ThreadChecker thread_checker_;
85     Flag** handle_;
86   };
87 
88   WeakReference();
89   WeakReference(Flag* flag);
90   ~WeakReference();
91 
92   bool is_valid() const;
93 
94  private:
95   scoped_refptr<Flag> flag_;
96 };
97 
98 class BASE_API WeakReferenceOwner {
99  public:
100   WeakReferenceOwner();
101   ~WeakReferenceOwner();
102 
103   WeakReference GetRef() const;
104 
HasRefs()105   bool HasRefs() const {
106     return flag_ != NULL;
107   }
108 
109   void Invalidate();
110 
111   // Indicates that this object will be used on another thread from now on.
DetachFromThread()112   void DetachFromThread() {
113     if (flag_) flag_->DetachFromThread();
114   }
115 
116  private:
117   mutable WeakReference::Flag* flag_;
118 };
119 
120 // This class simplifies the implementation of WeakPtr's type conversion
121 // 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
123 // base class gives us a way to access ref_ in a protected fashion.
124 class BASE_API WeakPtrBase {
125  public:
126   WeakPtrBase();
127   ~WeakPtrBase();
128 
129  protected:
130   WeakPtrBase(const WeakReference& ref);
131 
132   WeakReference ref_;
133 };
134 
135 }  // namespace internal
136 
137 template <typename T> class SupportsWeakPtr;
138 template <typename T> class WeakPtrFactory;
139 
140 // The WeakPtr class holds a weak reference to |T*|.
141 //
142 // This class is designed to be used like a normal pointer.  You should always
143 // null-test an object of this class before using it or invoking a method that
144 // may result in the underlying object being destroyed.
145 //
146 // EXAMPLE:
147 //
148 //   class Foo { ... };
149 //   WeakPtr<Foo> foo;
150 //   if (foo)
151 //     foo->method();
152 //
153 template <typename T>
154 class WeakPtr : public internal::WeakPtrBase {
155  public:
WeakPtr()156   WeakPtr() : ptr_(NULL) {
157   }
158 
159   // Allow conversion from U to T provided U "is a" T.
160   template <typename U>
WeakPtr(const WeakPtr<U> & other)161   WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.get()) {
162   }
163 
get()164   T* get() const { return ref_.is_valid() ? ptr_ : NULL; }
165   operator T*() const { return get(); }
166 
167   T* operator*() const {
168     DCHECK(get() != NULL);
169     return *get();
170   }
171   T* operator->() const {
172     DCHECK(get() != NULL);
173     return get();
174   }
175 
reset()176   void reset() {
177     ref_ = internal::WeakReference();
178     ptr_ = NULL;
179   }
180 
181  private:
182   friend class SupportsWeakPtr<T>;
183   friend class WeakPtrFactory<T>;
184 
WeakPtr(const internal::WeakReference & ref,T * ptr)185   WeakPtr(const internal::WeakReference& ref, T* ptr)
186       : WeakPtrBase(ref), ptr_(ptr) {
187   }
188 
189   // This pointer is only valid when ref_.is_valid() is true.  Otherwise, its
190   // value is undefined (as opposed to NULL).
191   T* ptr_;
192 };
193 
194 // A class may extend from SupportsWeakPtr to expose weak pointers to itself.
195 // This is useful in cases where you want others to be able to get a weak
196 // pointer to your class.  It also has the property that you don't need to
197 // initialize it from your constructor.
198 template <class T>
199 class SupportsWeakPtr {
200  public:
SupportsWeakPtr()201   SupportsWeakPtr() {}
202 
AsWeakPtr()203   WeakPtr<T> AsWeakPtr() {
204     return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this));
205   }
206 
207   // Indicates that this object will be used on another thread from now on.
DetachFromThread()208   void DetachFromThread() {
209     weak_reference_owner_.DetachFromThread();
210   }
211 
212  private:
213   internal::WeakReferenceOwner weak_reference_owner_;
214   DISALLOW_COPY_AND_ASSIGN(SupportsWeakPtr);
215 };
216 
217 // A class may alternatively be composed of a WeakPtrFactory and thereby
218 // control how it exposes weak pointers to itself.  This is helpful if you only
219 // need weak pointers within the implementation of a class.  This class is also
220 // useful when working with primitive types.  For example, you could have a
221 // WeakPtrFactory<bool> that is used to pass around a weak reference to a bool.
222 template <class T>
223 class WeakPtrFactory {
224  public:
WeakPtrFactory(T * ptr)225   explicit WeakPtrFactory(T* ptr) : ptr_(ptr) {
226   }
227 
GetWeakPtr()228   WeakPtr<T> GetWeakPtr() {
229     return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_);
230   }
231 
232   // Call this method to invalidate all existing weak pointers.
InvalidateWeakPtrs()233   void InvalidateWeakPtrs() {
234     weak_reference_owner_.Invalidate();
235   }
236 
237   // Call this method to determine if any weak pointers exist.
HasWeakPtrs()238   bool HasWeakPtrs() const {
239     return weak_reference_owner_.HasRefs();
240   }
241 
242   // Indicates that this object will be used on another thread from now on.
DetachFromThread()243   void DetachFromThread() {
244     weak_reference_owner_.DetachFromThread();
245   }
246 
247  private:
248   internal::WeakReferenceOwner weak_reference_owner_;
249   T* ptr_;
250   DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory);
251 };
252 
253 }  // namespace base
254 
255 #endif  // BASE_MEMORY_WEAK_PTR_H_
256