diff options
author | Josh Gao <jmgao@google.com> | 2021-05-20 19:15:15 -0700 |
---|---|---|
committer | Josh Gao <jmgao@google.com> | 2021-07-02 11:50:28 -0700 |
commit | 85407e35b880fcae9fd54639a527966963a51fe1 (patch) | |
tree | e0892d423302d50908ff0743620baab35da4959a | |
parent | 1ca6bba2815a04f6f222f2479dab80bae0fac659 (diff) | |
download | adb-85407e35b880fcae9fd54639a527966963a51fe1.tar.gz |
weak_ptr: add test, fix bug.
Add a test that uncovers a bug in weak_ptr where we don't call T's
destructor in enable_weak_from_this<T>::schedule_deletion.
Test: treehugger
Change-Id: I31d755cb2a240fa092acfa4cf627e67f3c8cd23f
-rw-r--r-- | types.h | 4 | ||||
-rw-r--r-- | types_test.cpp | 49 |
2 files changed, 50 insertions, 3 deletions
@@ -306,7 +306,7 @@ struct weak_ptr { return *this; } - T* get() { + T* get() const { check_main_thread(); return ptr_; } @@ -349,7 +349,7 @@ struct enable_weak_from_this { weak_ptr<T> weak() { return weak_ptr<T>(static_cast<T*>(this)); } void schedule_deletion() { - fdevent_run_on_main_thread([this]() { delete this; }); + fdevent_run_on_main_thread([this]() { delete static_cast<T*>(this); }); } private: diff --git a/types_test.cpp b/types_test.cpp index 564ae0bd..086a35dd 100644 --- a/types_test.cpp +++ b/types_test.cpp @@ -14,10 +14,14 @@ * limitations under the License. */ +#include "types.h" + #include <gtest/gtest.h> #include <memory> -#include "types.h" +#include <utility> + +#include "fdevent/fdevent_test.h" static IOVector::block_type create_block(const std::string& string) { return IOVector::block_type(string.begin(), string.end()); @@ -158,3 +162,46 @@ TEST(IOVector, trim_front) { vec.trim_front(); ASSERT_EQ(1ULL, vec.size()); } + +class weak_ptr_test : public FdeventTest {}; + +struct Destructor : public enable_weak_from_this<Destructor> { + Destructor(bool* destroyed) : destroyed_(destroyed) {} + ~Destructor() { *destroyed_ = true; } + + bool* destroyed_; +}; + +TEST_F(weak_ptr_test, smoke) { + PrepareThread(); + + Destructor* destructor = nullptr; + bool destroyed = false; + std::optional<weak_ptr<Destructor>> p; + + fdevent_run_on_main_thread([&p, &destructor, &destroyed]() { + destructor = new Destructor(&destroyed); + p = destructor->weak(); + ASSERT_TRUE(p->get()); + + p->reset(); + ASSERT_FALSE(p->get()); + + p->reset(destructor); + ASSERT_TRUE(p->get()); + }); + WaitForFdeventLoop(); + ASSERT_TRUE(destructor); + ASSERT_FALSE(destroyed); + + destructor->schedule_deletion(); + WaitForFdeventLoop(); + + ASSERT_TRUE(destroyed); + fdevent_run_on_main_thread([&p]() { + ASSERT_FALSE(p->get()); + p.reset(); + }); + + TerminateThread(); +} |