Bumping manifests a=b2g-bump
[gecko.git] / mfbt / WeakPtr.h
blob58960ad6177f0c2632bf9e96d83a583783d16ec2
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* Weak pointer functionality, implemented as a mixin for use with any class. */
9 /**
10 * SupportsWeakPtr lets you have a pointer to an object 'Foo' without affecting
11 * its lifetime. It works by creating a single shared reference counted object
12 * (WeakReference) that each WeakPtr will access 'Foo' through. This lets 'Foo'
13 * clear the pointer in the WeakReference without having to know about all of
14 * the WeakPtrs to it and allows the WeakReference to live beyond the lifetime
15 * of 'Foo'.
17 * PLEASE NOTE: This weak pointer implementation is not thread-safe.
19 * Note that when deriving from SupportsWeakPtr you should add
20 * MOZ_DECLARE_REFCOUNTED_TYPENAME(ClassName) to the public section of your
21 * class, where ClassName is the name of your class.
23 * The overhead of WeakPtr is that accesses to 'Foo' becomes an additional
24 * dereference, and an additional heap allocated pointer sized object shared
25 * between all of the WeakPtrs.
27 * Example of usage:
29 * // To have a class C support weak pointers, inherit from
30 * // SupportsWeakPtr<C>.
31 * class C : public SupportsWeakPtr<C>
32 * {
33 * public:
34 * MOZ_DECLARE_REFCOUNTED_TYPENAME(C)
35 * int mNum;
36 * void act();
37 * };
39 * C* ptr = new C();
41 * // Get weak pointers to ptr. The first time a weak pointer
42 * // is obtained, a reference counted WeakReference object is created that
43 * // can live beyond the lifetime of 'ptr'. The WeakReference
44 * // object will be notified of 'ptr's destruction.
45 * WeakPtr<C> weak = ptr;
46 * WeakPtr<C> other = ptr;
48 * // Test a weak pointer for validity before using it.
49 * if (weak) {
50 * weak->mNum = 17;
51 * weak->act();
52 * }
54 * // Destroying the underlying object clears weak pointers to it.
55 * delete ptr;
57 * MOZ_ASSERT(!weak, "Deleting |ptr| clears weak pointers to it.");
58 * MOZ_ASSERT(!other, "Deleting |ptr| clears all weak pointers to it.");
60 * WeakPtr is typesafe and may be used with any class. It is not required that
61 * the class be reference-counted or allocated in any particular way.
63 * The API was loosely inspired by Chromium's weak_ptr.h:
64 * http://src.chromium.org/svn/trunk/src/base/memory/weak_ptr.h
67 #ifndef mozilla_WeakPtr_h
68 #define mozilla_WeakPtr_h
70 #include "mozilla/ArrayUtils.h"
71 #include "mozilla/Assertions.h"
72 #include "mozilla/NullPtr.h"
73 #include "mozilla/RefPtr.h"
74 #include "mozilla/TypeTraits.h"
76 #include <string.h>
78 namespace mozilla {
80 template <typename T> class WeakPtr;
81 template <typename T> class SupportsWeakPtr;
83 namespace detail {
85 // This can live beyond the lifetime of the class derived from
86 // SupportsWeakPtr.
87 template<class T>
88 class WeakReference : public ::mozilla::RefCounted<WeakReference<T> >
90 public:
91 explicit WeakReference(T* p) : mPtr(p) {}
93 T* get() const { return mPtr; }
95 #ifdef MOZ_REFCOUNTED_LEAK_CHECKING
96 #ifdef XP_WIN
97 #define snprintf _snprintf
98 #endif
99 const char* typeName() const
101 static char nameBuffer[1024];
102 const char* innerType = mPtr->typeName();
103 // We could do fancier length checks at runtime, but innerType is
104 // controlled by us so we can ensure that this never causes a buffer
105 // overflow by this assertion.
106 MOZ_ASSERT(strlen(innerType) + sizeof("WeakReference<>") <
107 ArrayLength(nameBuffer),
108 "Exceedingly large type name");
109 snprintf(nameBuffer, ArrayLength(nameBuffer), "WeakReference<%s>",
110 innerType);
111 // This is usually not OK, but here we are returning a pointer to a static
112 // buffer which will immediately be used by the caller.
113 return nameBuffer;
116 size_t typeSize() const { return sizeof(*this); }
117 #undef snprintf
118 #endif
120 private:
121 friend class mozilla::SupportsWeakPtr<T>;
123 void detach() { mPtr = nullptr; }
125 T* mPtr;
128 } // namespace detail
130 template <typename T>
131 class SupportsWeakPtr
133 protected:
134 ~SupportsWeakPtr()
136 static_assert(IsBaseOf<SupportsWeakPtr<T>, T>::value,
137 "T must derive from SupportsWeakPtr<T>");
138 if (mSelfReferencingWeakPtr) {
139 mSelfReferencingWeakPtr.mRef->detach();
143 private:
144 const WeakPtr<T>& SelfReferencingWeakPtr()
146 if (!mSelfReferencingWeakPtr) {
147 mSelfReferencingWeakPtr.mRef = new detail::WeakReference<T>(static_cast<T*>(this));
149 return mSelfReferencingWeakPtr;
152 const WeakPtr<const T>& SelfReferencingWeakPtr() const
154 const WeakPtr<T>& p = const_cast<SupportsWeakPtr*>(this)->SelfReferencingWeakPtr();
155 return reinterpret_cast<const WeakPtr<const T>&>(p);
158 friend class WeakPtr<T>;
159 friend class WeakPtr<const T>;
161 WeakPtr<T> mSelfReferencingWeakPtr;
164 template <typename T>
165 class WeakPtr
167 typedef detail::WeakReference<T> WeakReference;
169 public:
170 WeakPtr& operator=(const WeakPtr& aOther)
172 mRef = aOther.mRef;
173 return *this;
176 WeakPtr(const WeakPtr& aOther)
178 *this = aOther;
181 WeakPtr& operator=(T* aOther)
183 return *this = aOther->SelfReferencingWeakPtr();
186 MOZ_IMPLICIT WeakPtr(T* aOther)
188 *this = aOther;
191 // Ensure that mRef is dereferenceable in the uninitialized state.
192 WeakPtr() : mRef(new WeakReference(nullptr)) {}
194 operator T*() const { return mRef->get(); }
195 T& operator*() const { return *mRef->get(); }
197 T* operator->() const { return mRef->get(); }
199 T* get() const { return mRef->get(); }
201 private:
202 friend class SupportsWeakPtr<T>;
204 explicit WeakPtr(const RefPtr<WeakReference>& aOther) : mRef(aOther) {}
206 RefPtr<WeakReference> mRef;
209 } // namespace mozilla
211 #endif /* mozilla_WeakPtr_h */