Loading include/utils/StrongPointer.h +34 −0 Original line number Diff line number Diff line Loading @@ -62,8 +62,10 @@ public: sp(T* other); sp(const sp<T>& other); sp(sp<T>&& other); template<typename U> sp(U* other); template<typename U> sp(const sp<U>& other); template<typename U> sp(sp<U>&& other); ~sp(); Loading @@ -71,8 +73,10 @@ public: sp& operator = (T* other); sp& operator = (const sp<T>& other); sp& operator = (sp<T>&& other); template<typename U> sp& operator = (const sp<U>& other); template<typename U> sp& operator = (sp<U>&& other); template<typename U> sp& operator = (U* other); //! Special optimization for use by ProcessState (and nobody else). Loading Loading @@ -123,6 +127,12 @@ sp<T>::sp(const sp<T>& other) m_ptr->incStrong(this); } template<typename T> sp<T>::sp(sp<T>&& other) : m_ptr(other.m_ptr) { other.m_ptr = nullptr; } template<typename T> template<typename U> sp<T>::sp(U* other) : m_ptr(other) { Loading @@ -137,6 +147,12 @@ sp<T>::sp(const sp<U>& other) m_ptr->incStrong(this); } template<typename T> template<typename U> sp<T>::sp(sp<U>&& other) : m_ptr(other.m_ptr) { other.m_ptr = nullptr; } template<typename T> sp<T>::~sp() { if (m_ptr) Loading @@ -154,6 +170,15 @@ sp<T>& sp<T>::operator =(const sp<T>& other) { return *this; } template<typename T> sp<T>& sp<T>::operator =(sp<T>&& other) { if (m_ptr) m_ptr->decStrong(this); m_ptr = other.m_ptr; other.m_ptr = nullptr; return *this; } template<typename T> sp<T>& sp<T>::operator =(T* other) { if (other) Loading @@ -175,6 +200,15 @@ sp<T>& sp<T>::operator =(const sp<U>& other) { return *this; } template<typename T> template<typename U> sp<T>& sp<T>::operator =(sp<U>&& other) { if (m_ptr) m_ptr->decStrong(this); m_ptr = other.m_ptr; other.m_ptr = nullptr; return *this; } template<typename T> template<typename U> sp<T>& sp<T>::operator =(U* other) { if (other) Loading libutils/tests/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ LOCAL_SRC_FILES := \ Looper_test.cpp \ LruCache_test.cpp \ String8_test.cpp \ StrongPointer_test.cpp \ Unicode_test.cpp \ Vector_test.cpp \ Loading libutils/tests/StrongPointer_test.cpp 0 → 100644 +58 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <gtest/gtest.h> #include <utils/StrongPointer.h> #include <utils/RefBase.h> using namespace android; class Foo : public LightRefBase<Foo> { public: Foo(bool* deleted_check) : mDeleted(deleted_check) { *mDeleted = false; } ~Foo() { *mDeleted = true; } private: bool* mDeleted; }; TEST(StrongPointer, move) { bool isDeleted; Foo* foo = new Foo(&isDeleted); ASSERT_EQ(0, foo->getStrongCount()); ASSERT_FALSE(isDeleted) << "Already deleted...?"; sp<Foo> sp1(foo); ASSERT_EQ(1, foo->getStrongCount()); { sp<Foo> sp2 = std::move(sp1); ASSERT_EQ(1, foo->getStrongCount()) << "std::move failed, incremented refcnt"; ASSERT_EQ(nullptr, sp1.get()) << "std::move failed, sp1 is still valid"; // The strong count isn't increasing, let's double check the old object // is properly reset and doesn't early delete sp1 = std::move(sp2); } ASSERT_FALSE(isDeleted) << "deleted too early! still has a reference!"; { // Now let's double check it deletes on time sp<Foo> sp2 = std::move(sp1); } ASSERT_TRUE(isDeleted) << "foo was leaked!"; } Loading
include/utils/StrongPointer.h +34 −0 Original line number Diff line number Diff line Loading @@ -62,8 +62,10 @@ public: sp(T* other); sp(const sp<T>& other); sp(sp<T>&& other); template<typename U> sp(U* other); template<typename U> sp(const sp<U>& other); template<typename U> sp(sp<U>&& other); ~sp(); Loading @@ -71,8 +73,10 @@ public: sp& operator = (T* other); sp& operator = (const sp<T>& other); sp& operator = (sp<T>&& other); template<typename U> sp& operator = (const sp<U>& other); template<typename U> sp& operator = (sp<U>&& other); template<typename U> sp& operator = (U* other); //! Special optimization for use by ProcessState (and nobody else). Loading Loading @@ -123,6 +127,12 @@ sp<T>::sp(const sp<T>& other) m_ptr->incStrong(this); } template<typename T> sp<T>::sp(sp<T>&& other) : m_ptr(other.m_ptr) { other.m_ptr = nullptr; } template<typename T> template<typename U> sp<T>::sp(U* other) : m_ptr(other) { Loading @@ -137,6 +147,12 @@ sp<T>::sp(const sp<U>& other) m_ptr->incStrong(this); } template<typename T> template<typename U> sp<T>::sp(sp<U>&& other) : m_ptr(other.m_ptr) { other.m_ptr = nullptr; } template<typename T> sp<T>::~sp() { if (m_ptr) Loading @@ -154,6 +170,15 @@ sp<T>& sp<T>::operator =(const sp<T>& other) { return *this; } template<typename T> sp<T>& sp<T>::operator =(sp<T>&& other) { if (m_ptr) m_ptr->decStrong(this); m_ptr = other.m_ptr; other.m_ptr = nullptr; return *this; } template<typename T> sp<T>& sp<T>::operator =(T* other) { if (other) Loading @@ -175,6 +200,15 @@ sp<T>& sp<T>::operator =(const sp<U>& other) { return *this; } template<typename T> template<typename U> sp<T>& sp<T>::operator =(sp<U>&& other) { if (m_ptr) m_ptr->decStrong(this); m_ptr = other.m_ptr; other.m_ptr = nullptr; return *this; } template<typename T> template<typename U> sp<T>& sp<T>::operator =(U* other) { if (other) Loading
libutils/tests/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ LOCAL_SRC_FILES := \ Looper_test.cpp \ LruCache_test.cpp \ String8_test.cpp \ StrongPointer_test.cpp \ Unicode_test.cpp \ Vector_test.cpp \ Loading
libutils/tests/StrongPointer_test.cpp 0 → 100644 +58 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <gtest/gtest.h> #include <utils/StrongPointer.h> #include <utils/RefBase.h> using namespace android; class Foo : public LightRefBase<Foo> { public: Foo(bool* deleted_check) : mDeleted(deleted_check) { *mDeleted = false; } ~Foo() { *mDeleted = true; } private: bool* mDeleted; }; TEST(StrongPointer, move) { bool isDeleted; Foo* foo = new Foo(&isDeleted); ASSERT_EQ(0, foo->getStrongCount()); ASSERT_FALSE(isDeleted) << "Already deleted...?"; sp<Foo> sp1(foo); ASSERT_EQ(1, foo->getStrongCount()); { sp<Foo> sp2 = std::move(sp1); ASSERT_EQ(1, foo->getStrongCount()) << "std::move failed, incremented refcnt"; ASSERT_EQ(nullptr, sp1.get()) << "std::move failed, sp1 is still valid"; // The strong count isn't increasing, let's double check the old object // is properly reset and doesn't early delete sp1 = std::move(sp2); } ASSERT_FALSE(isDeleted) << "deleted too early! still has a reference!"; { // Now let's double check it deletes on time sp<Foo> sp2 = std::move(sp1); } ASSERT_TRUE(isDeleted) << "foo was leaked!"; }