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. */
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
17 * The overhead of WeakPtr is that accesses to 'Foo' becomes an additional
18 * dereference, and an additional heap allocated pointer sized object shared
19 * between all of the WeakPtrs.
23 * // To have a class C support weak pointers, inherit from SupportsWeakPtr<C>.
24 * class C : public SupportsWeakPtr<C>
33 * // Get weak pointers to ptr. The first time asWeakPtr is called
34 * // a reference counted WeakReference object is created that
35 * // can live beyond the lifetime of 'ptr'. The WeakReference
36 * // object will be notified of 'ptr's destruction.
37 * WeakPtr<C> weak = ptr->asWeakPtr();
38 * WeakPtr<C> other = ptr->asWeakPtr();
40 * // Test a weak pointer for validity before using it.
46 * // Destroying the underlying object clears weak pointers to it.
49 * MOZ_ASSERT(!weak, "Deleting |ptr| clears weak pointers to it.");
50 * MOZ_ASSERT(!other, "Deleting |ptr| clears all weak pointers to it.");
52 * WeakPtr is typesafe and may be used with any class. It is not required that
53 * the class be reference-counted or allocated in any particular way.
55 * The API was loosely inspired by Chromium's weak_ptr.h:
56 * http://src.chromium.org/svn/trunk/src/base/memory/weak_ptr.h
59 #ifndef mozilla_WeakPtr_h
60 #define mozilla_WeakPtr_h
62 #include "mozilla/Assertions.h"
63 #include "mozilla/NullPtr.h"
64 #include "mozilla/RefPtr.h"
65 #include "mozilla/TypeTraits.h"
69 template <typename T
, class WeakReference
> class WeakPtrBase
;
70 template <typename T
, class WeakReference
> class SupportsWeakPtrBase
;
74 // This can live beyond the lifetime of the class derived from SupportsWeakPtrBase.
76 class WeakReference
: public ::mozilla::RefCounted
<WeakReference
<T
> >
79 explicit WeakReference(T
* p
) : ptr(p
) {}
85 friend class WeakPtrBase
<T
, WeakReference
<T
> >;
86 friend class SupportsWeakPtrBase
<T
, WeakReference
<T
> >;
95 template <typename T
, class WeakReference
>
96 class SupportsWeakPtrBase
99 WeakPtrBase
<T
, WeakReference
> asWeakPtr() {
101 weakRef
= new WeakReference(static_cast<T
*>(this));
102 return WeakPtrBase
<T
, WeakReference
>(weakRef
);
106 ~SupportsWeakPtrBase() {
107 static_assert(IsBaseOf
<SupportsWeakPtrBase
<T
, WeakReference
>, T
>::value
,
108 "T must derive from SupportsWeakPtrBase<T, WeakReference>");
114 friend class WeakPtrBase
<T
, WeakReference
>;
116 RefPtr
<WeakReference
> weakRef
;
119 template <typename T
>
120 class SupportsWeakPtr
: public SupportsWeakPtrBase
<T
, detail::WeakReference
<T
> >
124 template <typename T
, class WeakReference
>
128 WeakPtrBase(const WeakPtrBase
<T
, WeakReference
>& o
) : ref(o
.ref
) {}
129 // Ensure that ref is dereferenceable in the uninitialized state
130 WeakPtrBase() : ref(new WeakReference(nullptr)) {}
132 operator T
*() const {
135 T
& operator*() const {
139 T
* operator->() const {
148 friend class SupportsWeakPtrBase
<T
, WeakReference
>;
150 explicit WeakPtrBase(const RefPtr
<WeakReference
> &o
) : ref(o
) {}
152 RefPtr
<WeakReference
> ref
;
155 template <typename T
>
156 class WeakPtr
: public WeakPtrBase
<T
, detail::WeakReference
<T
> >
158 typedef WeakPtrBase
<T
, detail::WeakReference
<T
> > Base
;
160 WeakPtr(const WeakPtr
<T
>& o
) : Base(o
) {}
161 WeakPtr(const Base
& o
) : Base(o
) {}
165 } // namespace mozilla
167 #endif /* mozilla_WeakPtr_h */