RefBase: document 0 strong count, wp<>::promote
Explanation within. This shows the errorprone behavior
of the implicit wp<> constructor and justifies why we
recommend wp<>::fromExisting.
Bug: 393013610
Test: libutils_binder_test
Change-Id: I323b2902f0ae58da8512bdbc80377b5c5865294d
diff --git a/libutils/binder/RefBase_test.cpp b/libutils/binder/RefBase_test.cpp
index 65d40a2..36d1a4a 100644
--- a/libutils/binder/RefBase_test.cpp
+++ b/libutils/binder/RefBase_test.cpp
@@ -265,6 +265,37 @@
delete foo;
}
+TEST(RefBase, NoStrongCountPromoteFromWeak) {
+ bool isDeleted;
+ Foo* foo = new Foo(&isDeleted);
+
+ wp<Foo> weakFoo = wp<Foo>(foo);
+
+ EXPECT_FALSE(isDeleted);
+
+ {
+ sp<Foo> strongFoo = weakFoo.promote();
+ EXPECT_EQ(strongFoo, foo);
+ }
+
+ // this shows the justification of wp<>::fromExisting.
+ // if you construct a wp<>, for instance in a constructor, and it is
+ // accidentally promoted, that promoted sp<> will exclusively own
+ // the object. If that happens during the initialization of the
+ // object or in this scope, as you can see 'Foo* foo' is unowned,
+ // then we are left with a deleted object, and we could not put it
+ // into an sp<>.
+ //
+ // Consider the other implementation, where we disallow promoting
+ // a wp<> if there are no strong counts. If we return null, then
+ // the object would be unpromotable even though it hasn't been deleted.
+ // This is also errorprone.
+ //
+ // attemptIncStrong aborting in this case is a backwards incompatible
+ // change due to frequent use of wp<T>(this) in the constructor.
+ EXPECT_TRUE(isDeleted);
+}
+
TEST(RefBase, DoubleOwnershipDeath) {
bool isDeleted;
auto foo = sp<Foo>::make(&isDeleted);