1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* Weak pointer functionality, implemented as a mixin for use with any class. */
9 * SupportsWeakPtr lets you have a pointer to an object 'Foo' without affecting
10 * its lifetime. It works by creating a single shared reference counted object
11 * (WeakReference) that each WeakPtr will access 'Foo' through. This lets 'Foo'
12 * clear the pointer in the WeakReference without having to know about all of
13 * the WeakPtrs to it and allows the WeakReference to live beyond the lifetime
16 * AtomicSupportsWeakPtr can be used for a variant with an atomically updated
19 * The overhead of WeakPtr is that accesses to 'Foo' becomes an additional
20 * dereference, and an additional heap allocated pointer sized object shared
21 * between all of the WeakPtrs.
25 * // To have a class C support weak pointers, inherit from SupportsWeakPtr<C>.
26 * class C : public SupportsWeakPtr<C>
35 * // Get weak pointers to ptr. The first time asWeakPtr is called
36 * // a reference counted WeakReference object is created that
37 * // can live beyond the lifetime of 'ptr'. The WeakReference
38 * // object will be notified of 'ptr's destruction.
39 * WeakPtr<C> weak = ptr->asWeakPtr();
40 * WeakPtr<C> other = ptr->asWeakPtr();
42 * // Test a weak pointer for validity before using it.
48 * // Destroying the underlying object clears weak pointers to it.
51 * MOZ_ASSERT(!weak, "Deleting |ptr| clears weak pointers to it.");
52 * MOZ_ASSERT(!other, "Deleting |ptr| clears all weak pointers to it.");
54 * WeakPtr is typesafe and may be used with any class. It is not required that
55 * the class be reference-counted or allocated in any particular way.
57 * The API was loosely inspired by Chromium's weak_ptr.h:
58 * http://src.chromium.org/svn/trunk/src/base/memory/weak_ptr.h
61 #ifndef mozilla_WeakPtr_h_
62 #define mozilla_WeakPtr_h_
64 #include "mozilla/Assertions.h"
65 #include "mozilla/Atomics.h"
66 #include "mozilla/NullPtr.h"
67 #include "mozilla/RefPtr.h"
68 #include "mozilla/TypeTraits.h"
72 template <typename T
, class WeakReference
> class WeakPtrBase
;
73 template <typename T
, class WeakReference
> class SupportsWeakPtrBase
;
77 // This can live beyond the lifetime of the class derived from SupportsWeakPtrBase.
78 template<class T
, RefCountAtomicity Atomicity
>
79 class WeakReference
: public RefCounted
<WeakReference
<T
, Atomicity
>, Atomicity
>
82 explicit WeakReference(T
* p
) : ptr(p
) {}
88 friend class WeakPtrBase
<T
, WeakReference
>;
89 friend class SupportsWeakPtrBase
<T
, WeakReference
>;
98 template <typename T
, class WeakReference
>
99 class SupportsWeakPtrBase
102 WeakPtrBase
<T
, WeakReference
> asWeakPtr() {
104 weakRef
= new WeakReference(static_cast<T
*>(this));
105 return WeakPtrBase
<T
, WeakReference
>(weakRef
);
109 ~SupportsWeakPtrBase() {
110 MOZ_STATIC_ASSERT((IsBaseOf
<SupportsWeakPtrBase
<T
, WeakReference
>, T
>::value
),
111 "T must derive from SupportsWeakPtrBase<T, WeakReference>");
117 friend class WeakPtrBase
<T
, WeakReference
>;
119 RefPtr
<WeakReference
> weakRef
;
122 template <typename T
>
123 class SupportsWeakPtr
124 : public SupportsWeakPtrBase
<T
, detail::WeakReference
<T
, detail::NonAtomicRefCount
> >
128 template <typename T
>
129 class AtomicSupportsWeakPtr
130 : public SupportsWeakPtrBase
<T
, detail::WeakReference
<T
, detail::AtomicRefCount
> >
136 template <typename T
>
137 struct WeakReferenceCount
139 static const RefCountAtomicity atomicity
=
140 IsBaseOf
<AtomicSupportsWeakPtr
<T
>, T
>::value
147 template <typename T
, class WeakReference
>
151 WeakPtrBase(const WeakPtrBase
<T
, WeakReference
>& o
) : ref(o
.ref
) {}
152 // Ensure that ref is dereferenceable in the uninitialized state
153 WeakPtrBase() : ref(new WeakReference(nullptr)) {}
155 operator T
*() const {
158 T
& operator*() const {
162 T
* operator->() const {
171 friend class SupportsWeakPtrBase
<T
, WeakReference
>;
173 explicit WeakPtrBase(const RefPtr
<WeakReference
> &o
) : ref(o
) {}
175 RefPtr
<WeakReference
> ref
;
178 template <typename T
>
179 class WeakPtr
: public WeakPtrBase
<T
, detail::WeakReference
<T
, detail::WeakReferenceCount
<T
>::atomicity
> >
181 typedef WeakPtrBase
<T
, detail::WeakReference
<T
, detail::WeakReferenceCount
<T
>::atomicity
> > Base
;
183 WeakPtr(const WeakPtr
<T
>& o
) : Base(o
) {}
184 WeakPtr(const Base
& o
) : Base(o
) {}
188 } // namespace mozilla
190 #endif /* ifdef mozilla_WeakPtr_h_ */