Merge "Revert "Fix wp and sp comparison bugs""
diff --git a/libutils/RefBase_test.cpp b/libutils/RefBase_test.cpp
index b594ca5..2e0cf6e 100644
--- a/libutils/RefBase_test.cpp
+++ b/libutils/RefBase_test.cpp
@@ -45,44 +45,6 @@
bool* mDeleted;
};
-// A version of Foo that ensures that all objects are allocated at the same
-// address. No more than one can be allocated at a time. Thread-hostile.
-class FooFixedAlloc : public RefBase {
-public:
- static void* operator new(size_t size) {
- if (mAllocCount != 0) {
- abort();
- }
- mAllocCount = 1;
- if (theMemory == nullptr) {
- theMemory = malloc(size);
- }
- return theMemory;
- }
-
- static void operator delete(void *p) {
- if (mAllocCount != 1 || p != theMemory) {
- abort();
- }
- mAllocCount = 0;
- }
-
- FooFixedAlloc(bool* deleted_check) : mDeleted(deleted_check) {
- *mDeleted = false;
- }
-
- ~FooFixedAlloc() {
- *mDeleted = true;
- }
-private:
- bool* mDeleted;
- static int mAllocCount;
- static void* theMemory;
-};
-
-int FooFixedAlloc::mAllocCount(0);
-void* FooFixedAlloc::theMemory(nullptr);
-
TEST(RefBase, StrongMoves) {
bool isDeleted;
Foo* foo = new Foo(&isDeleted);
@@ -128,91 +90,6 @@
ASSERT_FALSE(isDeleted) << "Deletion on wp destruction should no longer occur";
}
-TEST(RefBase, Comparisons) {
- bool isDeleted, isDeleted2;
- Foo* foo = new Foo(&isDeleted);
- Foo* foo2 = new Foo(&isDeleted2);
- sp<Foo> sp1(foo);
- sp<Foo> sp2(foo2);
- wp<Foo> wp1(sp1);
- wp<Foo> wp2(sp1);
- wp<Foo> wp3(sp2);
- ASSERT_TRUE(wp1 == wp2);
- ASSERT_TRUE(wp1 == sp1);
- ASSERT_TRUE(wp3 == sp2);
- ASSERT_TRUE(wp1 != sp2);
- ASSERT_TRUE(wp1 <= wp2);
- ASSERT_TRUE(wp1 >= wp2);
- ASSERT_FALSE(wp1 != wp2);
- ASSERT_FALSE(wp1 > wp2);
- ASSERT_FALSE(wp1 < wp2);
- ASSERT_FALSE(sp1 == sp2);
- ASSERT_TRUE(sp1 != sp2);
- bool sp1_smaller = sp1 < sp2;
- wp<Foo>wp_smaller = sp1_smaller ? wp1 : wp3;
- wp<Foo>wp_larger = sp1_smaller ? wp3 : wp1;
- ASSERT_TRUE(wp_smaller < wp_larger);
- ASSERT_TRUE(wp_smaller != wp_larger);
- ASSERT_TRUE(wp_smaller <= wp_larger);
- ASSERT_FALSE(wp_smaller == wp_larger);
- ASSERT_FALSE(wp_smaller > wp_larger);
- ASSERT_FALSE(wp_smaller >= wp_larger);
- sp2 = nullptr;
- ASSERT_TRUE(isDeleted2);
- ASSERT_FALSE(isDeleted);
- ASSERT_FALSE(wp3 == sp2);
- // Comparison results on weak pointers should not be affected.
- ASSERT_TRUE(wp_smaller < wp_larger);
- ASSERT_TRUE(wp_smaller != wp_larger);
- ASSERT_TRUE(wp_smaller <= wp_larger);
- ASSERT_FALSE(wp_smaller == wp_larger);
- ASSERT_FALSE(wp_smaller > wp_larger);
- ASSERT_FALSE(wp_smaller >= wp_larger);
- wp2 = nullptr;
- ASSERT_FALSE(wp1 == wp2);
- ASSERT_TRUE(wp1 != wp2);
- wp1.clear();
- ASSERT_TRUE(wp1 == wp2);
- ASSERT_FALSE(wp1 != wp2);
- wp3.clear();
- ASSERT_TRUE(wp1 == wp3);
- ASSERT_FALSE(wp1 != wp3);
- ASSERT_FALSE(isDeleted);
- sp1.clear();
- ASSERT_TRUE(isDeleted);
- ASSERT_TRUE(sp1 == sp2);
-}
-
-// Check whether comparison against dead wp works, even if the object referenced
-// by the new wp happens to be at the same address.
-TEST(RefBase, ReplacedComparison) {
- bool isDeleted, isDeleted2;
- FooFixedAlloc* foo = new FooFixedAlloc(&isDeleted);
- sp<FooFixedAlloc> sp1(foo);
- wp<FooFixedAlloc> wp1(sp1);
- ASSERT_TRUE(wp1 == sp1);
- sp1.clear(); // Deallocates the object.
- ASSERT_TRUE(isDeleted);
- FooFixedAlloc* foo2 = new FooFixedAlloc(&isDeleted2);
- ASSERT_FALSE(isDeleted2);
- ASSERT_EQ(foo, foo2); // Not technically a legal comparison, but ...
- sp<FooFixedAlloc> sp2(foo2);
- wp<FooFixedAlloc> wp2(sp2);
- ASSERT_TRUE(sp2 == wp2);
- ASSERT_FALSE(sp2 != wp2);
- ASSERT_TRUE(sp2 != wp1);
- ASSERT_FALSE(sp2 == wp1);
- ASSERT_FALSE(sp2 == sp1); // sp1 is null.
- ASSERT_FALSE(wp1 == wp2); // wp1 refers to old object.
- ASSERT_TRUE(wp1 != wp2);
- ASSERT_TRUE(wp1 > wp2 || wp1 < wp2);
- ASSERT_TRUE(wp1 >= wp2 || wp1 <= wp2);
- ASSERT_FALSE(wp1 >= wp2 && wp1 <= wp2);
- ASSERT_FALSE(wp1 == nullptr);
- wp1 = sp2;
- ASSERT_TRUE(wp1 == wp2);
- ASSERT_FALSE(wp1 != wp2);
-}
// Set up a situation in which we race with visit2AndRremove() to delete
// 2 strong references. Bar destructor checks that there are no early
diff --git a/libutils/include/utils/RefBase.h b/libutils/include/utils/RefBase.h
index 730d631..1780cf2 100644
--- a/libutils/include/utils/RefBase.h
+++ b/libutils/include/utils/RefBase.h
@@ -171,8 +171,6 @@
#define ANDROID_REF_BASE_H
#include <atomic>
-#include <functional>
-#include <type_traits> // for common_type.
#include <stdint.h>
#include <sys/types.h>
@@ -194,26 +192,19 @@
// ---------------------------------------------------------------------------
#define COMPARE_WEAK(_op_) \
+inline bool operator _op_ (const sp<T>& o) const { \
+ return m_ptr _op_ o.m_ptr; \
+} \
+inline bool operator _op_ (const T* o) const { \
+ return m_ptr _op_ o; \
+} \
+template<typename U> \
+inline bool operator _op_ (const sp<U>& o) const { \
+ return m_ptr _op_ o.m_ptr; \
+} \
template<typename U> \
inline bool operator _op_ (const U* o) const { \
return m_ptr _op_ o; \
-} \
-/* Needed to handle type inference for nullptr: */ \
-inline bool operator _op_ (const T* o) const { \
- return m_ptr _op_ o; \
-}
-
-template<template<typename C> class comparator, typename T, typename U>
-static inline bool _wp_compare_(T* a, U* b) {
- return comparator<typename std::common_type<T*, U*>::type>()(a, b);
-}
-
-// Use std::less and friends to avoid undefined behavior when ordering pointers
-// to different objects.
-#define COMPARE_WEAK_FUNCTIONAL(_op_, _compare_) \
-template<typename U> \
-inline bool operator _op_ (const U* o) const { \
- return _wp_compare_<_compare_>(m_ptr, o); \
}
// ---------------------------------------------------------------------------
@@ -404,51 +395,39 @@
COMPARE_WEAK(==)
COMPARE_WEAK(!=)
- COMPARE_WEAK_FUNCTIONAL(>, std::greater)
- COMPARE_WEAK_FUNCTIONAL(<, std::less)
- COMPARE_WEAK_FUNCTIONAL(<=, std::less_equal)
- COMPARE_WEAK_FUNCTIONAL(>=, std::greater_equal)
+ COMPARE_WEAK(>)
+ COMPARE_WEAK(<)
+ COMPARE_WEAK(<=)
+ COMPARE_WEAK(>=)
+ inline bool operator == (const wp<T>& o) const {
+ return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
+ }
template<typename U>
inline bool operator == (const wp<U>& o) const {
- return m_refs == o.m_refs; // Implies m_ptr == o.mptr; see invariants below.
+ return m_ptr == o.m_ptr;
}
- template<typename U>
- inline bool operator == (const sp<U>& o) const {
- // Just comparing m_ptr fields is often dangerous, since wp<> may refer to an older
- // object at the same address.
- if (o == nullptr) {
- return m_ptr == nullptr;
- } else {
- return m_refs == o->getWeakRefs(); // Implies m_ptr == o.mptr.
- }
+ inline bool operator > (const wp<T>& o) const {
+ return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
}
-
- template<typename U>
- inline bool operator != (const sp<U>& o) const {
- return !(*this == o);
- }
-
template<typename U>
inline bool operator > (const wp<U>& o) const {
- if (m_ptr == o.m_ptr) {
- return _wp_compare_<std::greater>(m_refs, o.m_refs);
- } else {
- return _wp_compare_<std::greater>(m_ptr, o.m_ptr);
- }
+ return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
}
+ inline bool operator < (const wp<T>& o) const {
+ return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
+ }
template<typename U>
inline bool operator < (const wp<U>& o) const {
- if (m_ptr == o.m_ptr) {
- return _wp_compare_<std::less>(m_refs, o.m_refs);
- } else {
- return _wp_compare_<std::less>(m_ptr, o.m_ptr);
- }
+ return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
}
+ inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
+ inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
+ inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
private:
@@ -467,22 +446,6 @@
// ---------------------------------------------------------------------------
// No user serviceable parts below here.
-// Implementation invariants:
-// Either
-// 1) m_ptr and m_refs are both null, or
-// 2) m_refs == m_ptr->mRefs, or
-// 3) *m_ptr is no longer live, and m_refs points to the weakref_type object that corresponded
-// to m_ptr while it was live. *m_refs remains live while a wp<> refers to it.
-//
-// The m_refs field in a RefBase object is allocated on construction, unique to that RefBase
-// object, and never changes. Thus if two wp's have identical m_refs fields, they are either both
-// null or point to the same object. If two wp's have identical m_ptr fields, they either both
-// point to the same live object and thus have the same m_ref fields, or at least one of the
-// objects is no longer live.
-//
-// Note that the above comparison operations go out of their way to provide an ordering consistent
-// with ordinary pointer comparison; otherwise they could ignore m_ptr, and just compare m_refs.
-
template<typename T>
wp<T>::wp(T* other)
: m_ptr(other)
@@ -632,7 +595,6 @@
{
if (m_ptr) {
m_refs->decWeak(this);
- m_refs = 0;
m_ptr = 0;
}
}
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h
index 9cd7c75..1571129 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -17,9 +17,6 @@
#ifndef ANDROID_STRONG_POINTER_H
#define ANDROID_STRONG_POINTER_H
-#include <functional>
-#include <type_traits> // for common_type.
-
// ---------------------------------------------------------------------------
namespace android {
@@ -27,12 +24,13 @@
// ---------------------------------------------------------------------------
-// TODO: Maybe remove sp<> ? wp<> comparison? These are dangerous: If the wp<>
-// was created before the sp<>, and they point to different objects, they may
-// compare equal even if they are entirely unrelated. E.g. CameraService
-// currently performa such comparisons.
-
-#define COMPARE_STRONG(_op_) \
+#define COMPARE(_op_) \
+inline bool operator _op_ (const sp<T>& o) const { \
+ return m_ptr _op_ o.m_ptr; \
+} \
+inline bool operator _op_ (const T* o) const { \
+ return m_ptr _op_ o; \
+} \
template<typename U> \
inline bool operator _op_ (const sp<U>& o) const { \
return m_ptr _op_ o.m_ptr; \
@@ -41,27 +39,14 @@
inline bool operator _op_ (const U* o) const { \
return m_ptr _op_ o; \
} \
-/* Needed to handle type inference for nullptr: */ \
-inline bool operator _op_ (const T* o) const { \
- return m_ptr _op_ o; \
+inline bool operator _op_ (const wp<T>& o) const { \
+ return m_ptr _op_ o.m_ptr; \
+} \
+template<typename U> \
+inline bool operator _op_ (const wp<U>& o) const { \
+ return m_ptr _op_ o.m_ptr; \
}
-template<template<typename C> class comparator, typename T, typename U>
-static inline bool _sp_compare_(T* a, U* b) {
- return comparator<typename std::common_type<T*, U*>::type>()(a, b);
-}
-
-// Use std::less and friends to avoid undefined behavior when ordering pointers
-// to different objects.
-#define COMPARE_STRONG_FUNCTIONAL(_op_, _compare_) \
-template<typename U> \
-inline bool operator _op_ (const sp<U>& o) const { \
- return _sp_compare_<_compare_>(m_ptr, o.m_ptr); \
-} \
-template<typename U> \
-inline bool operator _op_ (const U* o) const { \
- return _sp_compare_<_compare_>(m_ptr, o); \
-}
// ---------------------------------------------------------------------------
template<typename T>
@@ -104,23 +89,12 @@
// Operators
- COMPARE_STRONG(==)
- COMPARE_STRONG(!=)
- COMPARE_STRONG_FUNCTIONAL(>, std::greater)
- COMPARE_STRONG_FUNCTIONAL(<, std::less)
- COMPARE_STRONG_FUNCTIONAL(<=, std::less_equal)
- COMPARE_STRONG_FUNCTIONAL(>=, std::greater_equal)
-
- // Punt these to the wp<> implementation.
- template<typename U>
- inline bool operator == (const wp<U>& o) const {
- return o == *this;
- }
-
- template<typename U>
- inline bool operator != (const wp<U>& o) const {
- return o != *this;
- }
+ COMPARE(==)
+ COMPARE(!=)
+ COMPARE(>)
+ COMPARE(<)
+ COMPARE(<=)
+ COMPARE(>=)
private:
template<typename Y> friend class sp;