TestRefPtr.cpp (3146B)
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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/RefPtr.h" 8 #include "mozilla/RefCounted.h" 9 10 #include <type_traits> 11 12 using mozilla::RefCounted; 13 14 class Foo : public RefCounted<Foo> { 15 public: 16 MOZ_DECLARE_REFCOUNTED_TYPENAME(Foo) 17 18 Foo() : mDead(false) {} 19 20 static int sNumDestroyed; 21 22 ~Foo() { 23 MOZ_RELEASE_ASSERT(!mDead); 24 mDead = true; 25 sNumDestroyed++; 26 } 27 28 private: 29 bool mDead; 30 }; 31 int Foo::sNumDestroyed; 32 33 struct Bar : public Foo {}; 34 35 already_AddRefed<Foo> NewFoo() { 36 RefPtr<Foo> f(new Foo()); 37 return f.forget(); 38 } 39 40 already_AddRefed<Foo> NewBar() { 41 RefPtr<Bar> bar = new Bar(); 42 return bar.forget(); 43 } 44 45 void GetNewFoo(Foo** aFoo) { 46 *aFoo = new Bar(); 47 // Kids, don't try this at home 48 (*aFoo)->AddRef(); 49 } 50 51 void GetNewFoo(RefPtr<Foo>* aFoo) { *aFoo = new Bar(); } 52 53 already_AddRefed<Foo> GetNullFoo() { return 0; } 54 55 int main() { 56 MOZ_RELEASE_ASSERT(0 == Foo::sNumDestroyed); 57 { 58 RefPtr<Foo> f = new Foo(); 59 MOZ_RELEASE_ASSERT(f->refCount() == 1); 60 } 61 MOZ_RELEASE_ASSERT(1 == Foo::sNumDestroyed); 62 63 { 64 RefPtr f1 = NewFoo(); 65 static_assert(std::is_same_v<decltype(f1), RefPtr<Foo>>); 66 RefPtr f2(NewFoo()); 67 static_assert(std::is_same_v<decltype(f2), RefPtr<Foo>>); 68 MOZ_RELEASE_ASSERT(1 == Foo::sNumDestroyed); 69 } 70 MOZ_RELEASE_ASSERT(3 == Foo::sNumDestroyed); 71 72 { 73 RefPtr<Foo> b = NewBar(); 74 MOZ_RELEASE_ASSERT(3 == Foo::sNumDestroyed); 75 } 76 MOZ_RELEASE_ASSERT(4 == Foo::sNumDestroyed); 77 78 { 79 RefPtr<Foo> f1; 80 { 81 f1 = new Foo(); 82 RefPtr<Foo> f2(f1); 83 RefPtr<Foo> f3 = f2; 84 MOZ_RELEASE_ASSERT(4 == Foo::sNumDestroyed); 85 } 86 MOZ_RELEASE_ASSERT(4 == Foo::sNumDestroyed); 87 } 88 MOZ_RELEASE_ASSERT(5 == Foo::sNumDestroyed); 89 90 { 91 { 92 RefPtr<Foo> f = new Foo(); 93 RefPtr<Foo> g = f.forget(); 94 } 95 MOZ_RELEASE_ASSERT(6 == Foo::sNumDestroyed); 96 } 97 98 { 99 RefPtr<Foo> f = new Foo(); 100 GetNewFoo(getter_AddRefs(f)); 101 MOZ_RELEASE_ASSERT(7 == Foo::sNumDestroyed); 102 } 103 MOZ_RELEASE_ASSERT(8 == Foo::sNumDestroyed); 104 105 { 106 RefPtr<Foo> f = new Foo(); 107 GetNewFoo(&f); 108 MOZ_RELEASE_ASSERT(9 == Foo::sNumDestroyed); 109 } 110 MOZ_RELEASE_ASSERT(10 == Foo::sNumDestroyed); 111 112 { 113 RefPtr<Foo> f1 = new Bar(); 114 } 115 MOZ_RELEASE_ASSERT(11 == Foo::sNumDestroyed); 116 117 { 118 RefPtr f = GetNullFoo(); 119 static_assert(std::is_same_v<decltype(f), RefPtr<Foo>>); 120 MOZ_RELEASE_ASSERT(11 == Foo::sNumDestroyed); 121 } 122 MOZ_RELEASE_ASSERT(11 == Foo::sNumDestroyed); 123 124 { 125 RefPtr<Foo> f = new Foo(); 126 127 auto& alias = f; 128 f = std::move(static_cast<RefPtr<Foo>&>(alias)); 129 MOZ_RELEASE_ASSERT(11 == Foo::sNumDestroyed); 130 } 131 MOZ_RELEASE_ASSERT(12 == Foo::sNumDestroyed); 132 133 { 134 bool condition = true; 135 const auto f = 136 condition ? mozilla::MakeRefPtr<Bar>() : mozilla::MakeRefPtr<Foo>(); 137 138 MOZ_RELEASE_ASSERT(f); 139 } 140 141 return 0; 142 }