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 #include "mozilla/WeakPtr.h"
9 using mozilla::SupportsWeakPtr
;
10 using mozilla::WeakPtr
;
12 static char IamB
[] = "B";
13 static char IamC
[] = "C";
14 static char IamD
[] = "D";
16 class B
: public SupportsWeakPtr
{
18 char const* whoAmI() const { return IamB
; }
21 // To have a class C support weak pointers, inherit from SupportsWeakPtr.
22 class C
: public SupportsWeakPtr
{
29 // Setting mNum in the destructor allows us to test against use-after-free
34 char const* whoAmI() const { return IamC
; }
38 bool isConst() { return false; }
40 bool isConst() const { return true; }
43 // Derived from a class that supports weakptr, but doesn't implement itself
44 // To check upcast works as expected
47 char const* whoAmI() const { return IamD
; }
50 bool isConst(C
*) { return false; }
52 bool isConst(const C
*) { return true; }
56 MOZ_RELEASE_ASSERT(c1
->mNum
== 0);
58 // Get weak pointers to c1. The first time,
59 // a reference-counted WeakReference object is created that
60 // can live beyond the lifetime of 'c1'. The WeakReference
61 // object will be notified of 'c1's destruction.
63 // Test a weak pointer for validity before using it.
64 MOZ_RELEASE_ASSERT(w1
);
65 MOZ_RELEASE_ASSERT(w1
== c1
);
69 // Test taking another WeakPtr<C> to c1
71 MOZ_RELEASE_ASSERT(w2
);
72 MOZ_RELEASE_ASSERT(w2
== c1
);
73 MOZ_RELEASE_ASSERT(w2
== w1
);
74 MOZ_RELEASE_ASSERT(w2
->mNum
== 1);
76 // Test a WeakPtr<const C>
77 WeakPtr
<const C
> w3const
= c1
;
78 MOZ_RELEASE_ASSERT(w3const
);
79 MOZ_RELEASE_ASSERT(w3const
== c1
);
80 MOZ_RELEASE_ASSERT(w3const
== w1
);
81 MOZ_RELEASE_ASSERT(w3const
== w2
);
82 MOZ_RELEASE_ASSERT(w3const
->mNum
== 1);
84 // Test const-correctness of operator-> and operator T*
85 MOZ_RELEASE_ASSERT(!w1
->isConst());
86 MOZ_RELEASE_ASSERT(w3const
->isConst());
87 MOZ_RELEASE_ASSERT(!isConst(w1
));
88 MOZ_RELEASE_ASSERT(isConst(w3const
));
90 // Test that when a WeakPtr is destroyed, it does not destroy the object that
91 // it points to, and it does not affect other WeakPtrs pointing to the same
92 // object (e.g. it does not destroy the WeakReference object).
94 WeakPtr
<C
> w4local
= c1
;
95 MOZ_RELEASE_ASSERT(w4local
== c1
);
97 // Now w4local has gone out of scope. If that had destroyed c1, then the
98 // following would fail for sure (see C::~C()).
99 MOZ_RELEASE_ASSERT(c1
->mNum
== 1);
100 // Check that w4local going out of scope hasn't affected other WeakPtr's
102 MOZ_RELEASE_ASSERT(w1
== c1
);
103 MOZ_RELEASE_ASSERT(w2
== c1
);
105 // Now construct another C object and test changing what object a WeakPtr
109 MOZ_RELEASE_ASSERT(w2
->mNum
== 1); // w2 was pointing to c1
111 MOZ_RELEASE_ASSERT(w2
);
112 MOZ_RELEASE_ASSERT(w2
== c2
);
113 MOZ_RELEASE_ASSERT(w2
!= c1
);
114 MOZ_RELEASE_ASSERT(w2
!= w1
);
115 MOZ_RELEASE_ASSERT(w2
->mNum
== 2);
117 // Destroying the underlying object clears weak pointers to it.
118 // It should not affect pointers that are not currently pointing to it.
120 MOZ_RELEASE_ASSERT(!w1
, "Deleting an object should clear WeakPtr's to it.");
121 MOZ_RELEASE_ASSERT(!w3const
,
122 "Deleting an object should clear WeakPtr's to it.");
123 MOZ_RELEASE_ASSERT(w2
,
124 "Deleting an object should not clear WeakPtr that are not "
128 MOZ_RELEASE_ASSERT(!w2
, "Deleting an object should clear WeakPtr's to it.");
130 // Check that we correctly upcast to the base class supporting weakptr
134 // You should be able to use WeakPtr<D> even if it's a base class which
135 // implements SupportsWeakPtr.
136 WeakPtr
<D
> weakd
= d
;
138 MOZ_RELEASE_ASSERT(db
->whoAmI() == IamB
);
139 MOZ_RELEASE_ASSERT(weakd
.get() == db
.get());
143 MOZ_RELEASE_ASSERT(!db
);
144 MOZ_RELEASE_ASSERT(!weakd
);