Modified: trunk/Source/WTF/wtf/CompactPointerTuple.h (266712 => 266713)
--- trunk/Source/WTF/wtf/CompactPointerTuple.h 2020-09-08 01:35:14 UTC (rev 266712)
+++ trunk/Source/WTF/wtf/CompactPointerTuple.h 2020-09-08 03:50:14 UTC (rev 266713)
@@ -68,6 +68,12 @@
ASSERT(this->pointer() == pointer);
}
+ template<typename OtherPointerType, typename = std::enable_if<std::is_pointer<PointerType>::value && std::is_convertible<OtherPointerType, PointerType>::value>>
+ CompactPointerTuple(CompactPointerTuple<OtherPointerType, Type>&& other)
+ : m_data { std::exchange(other.m_data, { }) }
+ {
+ }
+
PointerType pointer() const { return bitwise_cast<PointerType>(m_data & pointerMask); }
void setPointer(PointerType pointer)
{
@@ -108,6 +114,13 @@
{
}
+ template<typename OtherPointerType, typename = std::enable_if<std::is_pointer<PointerType>::value && std::is_convertible<OtherPointerType, PointerType>::value>>
+ CompactPointerTuple(CompactPointerTuple<OtherPointerType, Type>&& other)
+ : m_pointer { std::exchange(other.m_pointer, { }) }
+ , m_type { std::exchange(other.m_type, { }) }
+ {
+ }
+
PointerType pointer() const { return m_pointer; }
void setPointer(PointerType pointer) { m_pointer = pointer; }
Type type() const { return m_type; }
@@ -117,6 +130,8 @@
PointerType m_pointer { nullptr };
Type m_type { 0 };
#endif
+
+ template<typename, typename> friend class CompactPointerTuple;
};
} // namespace WTF
Modified: trunk/Source/WTF/wtf/CompactUniquePtrTuple.h (266712 => 266713)
--- trunk/Source/WTF/wtf/CompactUniquePtrTuple.h 2020-09-08 01:35:14 UTC (rev 266712)
+++ trunk/Source/WTF/wtf/CompactUniquePtrTuple.h 2020-09-08 03:50:14 UTC (rev 266713)
@@ -40,7 +40,7 @@
}
template<typename T, typename Type, typename Deleter, typename... Args>
-ALWAYS_INLINE CompactUniquePtrTuple<T, Type> makeCompactUniquePtr(Args&&... args)
+ALWAYS_INLINE CompactUniquePtrTuple<T, Type, Deleter> makeCompactUniquePtr(Args&&... args)
{
return CompactUniquePtrTuple<T, Type, Deleter>(makeUnique<T>(std::forward<Args>(args)...));
}
@@ -52,8 +52,8 @@
public:
CompactUniquePtrTuple() = default;
- template <typename U>
- CompactUniquePtrTuple(CompactUniquePtrTuple<U, Type, Deleter>&& other)
+ template <typename U, typename UDeleter, typename = std::enable_if_t<std::is_same<UDeleter, Deleter>::value || std::is_same<UDeleter, std::default_delete<U>>::value>>
+ CompactUniquePtrTuple(CompactUniquePtrTuple<U, Type, UDeleter>&& other)
: m_data { std::exchange(other.m_data, { }) }
{
}
@@ -63,10 +63,10 @@
setPointer(nullptr);
}
- template <typename U>
- CompactUniquePtrTuple<T, Type, Deleter>& operator=(CompactUniquePtrTuple<U, Type, Deleter>&& other)
+ template <typename U, typename UDeleter, typename = std::enable_if_t<std::is_same<UDeleter, Deleter>::value || std::is_same<UDeleter, std::default_delete<U>>::value>>
+ CompactUniquePtrTuple<T, Type, Deleter>& operator=(CompactUniquePtrTuple<U, Type, UDeleter>&& other)
{
- auto moved = WTFMove(other);
+ CompactUniquePtrTuple moved { WTFMove(other) };
std::swap(m_data, moved.m_data);
return *this;
}
@@ -86,8 +86,8 @@
m_data.setPointer(nullptr);
}
- template <typename U>
- void setPointer(std::unique_ptr<U, Deleter>&& pointer)
+ template <typename U, typename UDeleter, typename = std::enable_if_t<std::is_same<UDeleter, Deleter>::value || std::is_same<UDeleter, std::default_delete<U>>::value>>
+ void setPointer(std::unique_ptr<U, UDeleter>&& pointer)
{
deletePointer();
m_data.setPointer(pointer.release());
@@ -115,6 +115,8 @@
template<typename U, typename E, typename... Args> friend CompactUniquePtrTuple<U, E> makeCompactUniquePtr(Args&&... args);
template<typename U, typename E, typename D, typename... Args> friend CompactUniquePtrTuple<U, E, D> makeCompactUniquePtr(Args&&... args);
+ template <typename, typename, typename> friend class CompactUniquePtrTuple;
+
CompactPointerTuple<T*, Type> m_data;
};
Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/CompactUniquePtrTuple.cpp (266712 => 266713)
--- trunk/Tools/TestWebKitAPI/Tests/WTF/CompactUniquePtrTuple.cpp 2020-09-08 01:35:14 UTC (rev 266712)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/CompactUniquePtrTuple.cpp 2020-09-08 03:50:14 UTC (rev 266713)
@@ -38,8 +38,8 @@
public:
A() { ++s_constructorCallCount; }
- ~A() { ++s_destructorCallCount; }
-
+ virtual ~A() { ++s_destructorCallCount; }
+
static unsigned s_constructorCallCount;
static unsigned s_destructorCallCount;
};
@@ -149,4 +149,177 @@
EXPECT_EQ(0xf2f2U, b.type());
}
+class B : public A {
+ WTF_MAKE_FAST_ALLOCATED;
+
+public:
+ B() { ++s_constructorCallCount; }
+ virtual ~B() { ++s_destructorCallCount; }
+
+ static unsigned s_constructorCallCount;
+ static unsigned s_destructorCallCount;
+};
+
+unsigned B::s_constructorCallCount = 0;
+unsigned B::s_destructorCallCount = 0;
+
+TEST(WTF_CompactUniquePtrTuple, Subclassing)
+{
+ A::s_constructorCallCount = 0;
+ A::s_destructorCallCount = 0;
+ B::s_constructorCallCount = 0;
+ B::s_destructorCallCount = 0;
+
+ CompactUniquePtrTuple<B, uint16_t> empty;
+ EXPECT_EQ(0U, A::s_constructorCallCount);
+ EXPECT_EQ(0U, A::s_destructorCallCount);
+ EXPECT_EQ(0U, B::s_constructorCallCount);
+ EXPECT_EQ(0U, B::s_destructorCallCount);
+ EXPECT_EQ(nullptr, empty.pointer());
+ EXPECT_EQ(0U, empty.type());
+
+ CompactUniquePtrTuple<B, uint16_t> b = makeCompactUniquePtr<B, uint16_t>();
+ EXPECT_EQ(1U, A::s_constructorCallCount);
+ EXPECT_EQ(0U, A::s_destructorCallCount);
+ EXPECT_EQ(1U, B::s_constructorCallCount);
+ EXPECT_EQ(0U, B::s_destructorCallCount);
+ EXPECT_NE(nullptr, b.pointer());
+ EXPECT_EQ(0U, b.type());
+
+ b.setType(0xff);
+ EXPECT_EQ(1U, A::s_constructorCallCount);
+ EXPECT_EQ(0U, A::s_destructorCallCount);
+ EXPECT_EQ(1U, B::s_constructorCallCount);
+ EXPECT_EQ(0U, B::s_destructorCallCount);
+ EXPECT_NE(nullptr, b.pointer());
+ EXPECT_EQ(0xffU, b.type());
+
+ b.setPointer(nullptr);
+ EXPECT_EQ(1U, A::s_constructorCallCount);
+ EXPECT_EQ(1U, A::s_destructorCallCount);
+ EXPECT_EQ(1U, B::s_constructorCallCount);
+ EXPECT_EQ(1U, B::s_destructorCallCount);
+ EXPECT_EQ(nullptr, b.pointer());
+ EXPECT_EQ(0xffU, b.type());
+
+ CompactUniquePtrTuple<A, uint16_t> a = makeCompactUniquePtr<B, uint16_t>();
+ EXPECT_EQ(2U, A::s_constructorCallCount);
+ EXPECT_EQ(1U, A::s_destructorCallCount);
+ EXPECT_EQ(2U, B::s_constructorCallCount);
+ EXPECT_EQ(1U, B::s_destructorCallCount);
+ EXPECT_NE(nullptr, a.pointer());
+ EXPECT_EQ(0U, a.type());
+
+ a.setType(0x1c);
+ EXPECT_EQ(2U, A::s_constructorCallCount);
+ EXPECT_EQ(1U, A::s_destructorCallCount);
+ EXPECT_EQ(2U, B::s_constructorCallCount);
+ EXPECT_EQ(1U, B::s_destructorCallCount);
+ EXPECT_NE(nullptr, a.pointer());
+ EXPECT_EQ(0x1cU, a.type());
+
+ auto* oldPointer = a.pointer();
+ a.setPointer(makeUnique<B>());
+ EXPECT_EQ(3U, A::s_constructorCallCount);
+ EXPECT_EQ(2U, A::s_destructorCallCount);
+ EXPECT_EQ(3U, B::s_constructorCallCount);
+ EXPECT_EQ(2U, B::s_destructorCallCount);
+ EXPECT_NE(oldPointer, a.pointer());
+ EXPECT_EQ(0x1cU, a.type());
+
+ a = makeCompactUniquePtr<A, uint16_t>();
+ EXPECT_EQ(4U, A::s_constructorCallCount);
+ EXPECT_EQ(3U, A::s_destructorCallCount);
+ EXPECT_EQ(3U, B::s_constructorCallCount);
+ EXPECT_EQ(3U, B::s_destructorCallCount);
+ EXPECT_NE(oldPointer, a.pointer());
+ EXPECT_EQ(0U, a.type());
+
+ a.setType(0xfed);
+ EXPECT_EQ(4U, A::s_constructorCallCount);
+ EXPECT_EQ(3U, A::s_destructorCallCount);
+ EXPECT_EQ(3U, B::s_constructorCallCount);
+ EXPECT_EQ(3U, B::s_destructorCallCount);
+ EXPECT_NE(nullptr, a.pointer());
+ EXPECT_EQ(0xfedU, a.type());
+
+ oldPointer = a.pointer();
+ auto uniqueA = a.moveToUniquePtr();
+ EXPECT_EQ(4U, A::s_constructorCallCount);
+ EXPECT_EQ(3U, A::s_destructorCallCount);
+ EXPECT_EQ(3U, B::s_constructorCallCount);
+ EXPECT_EQ(3U, B::s_destructorCallCount);
+ EXPECT_EQ(nullptr, a.pointer());
+ EXPECT_EQ(oldPointer, uniqueA.get());
+ EXPECT_EQ(0xfedU, a.type());
+
+ uniqueA = nullptr;
+ EXPECT_EQ(4U, A::s_constructorCallCount);
+ EXPECT_EQ(4U, A::s_destructorCallCount);
+ EXPECT_EQ(3U, B::s_constructorCallCount);
+ EXPECT_EQ(3U, B::s_destructorCallCount);
+ EXPECT_EQ(nullptr, a.pointer());
+ EXPECT_EQ(nullptr, uniqueA.get());
+ EXPECT_EQ(0xfedU, a.type());
+}
+
+struct ADeleter {
+ static unsigned s_callCount;
+
+ void operator()(A* a) const
+ {
+ ++s_callCount;
+ delete a;
+ }
+};
+
+unsigned ADeleter::s_callCount = 0;
+
+TEST(WTF_CompactUniquePtrTuple, Deleter)
+{
+ A::s_constructorCallCount = 0;
+ A::s_destructorCallCount = 0;
+ B::s_constructorCallCount = 0;
+ B::s_destructorCallCount = 0;
+ ADeleter::s_callCount = 0;
+
+ CompactUniquePtrTuple<B, uint16_t, ADeleter> empty;
+ EXPECT_EQ(0U, A::s_constructorCallCount);
+ EXPECT_EQ(0U, A::s_destructorCallCount);
+ EXPECT_EQ(0U, B::s_constructorCallCount);
+ EXPECT_EQ(0U, B::s_destructorCallCount);
+ EXPECT_EQ(0U, ADeleter::s_callCount);
+ EXPECT_EQ(nullptr, empty.pointer());
+ EXPECT_EQ(0U, empty.type());
+
+ CompactUniquePtrTuple<A, uint16_t, ADeleter> a = makeCompactUniquePtr<A, uint16_t, ADeleter>();
+ EXPECT_EQ(1U, A::s_constructorCallCount);
+ EXPECT_EQ(0U, A::s_destructorCallCount);
+ EXPECT_EQ(0U, B::s_constructorCallCount);
+ EXPECT_EQ(0U, B::s_destructorCallCount);
+ EXPECT_EQ(0U, ADeleter::s_callCount);
+ EXPECT_NE(nullptr, a.pointer());
+ EXPECT_EQ(0U, a.type());
+
+ a.setType(0x7e89U);
+ EXPECT_EQ(1U, A::s_constructorCallCount);
+ EXPECT_EQ(0U, A::s_destructorCallCount);
+ EXPECT_EQ(0U, B::s_constructorCallCount);
+ EXPECT_EQ(0U, B::s_destructorCallCount);
+ EXPECT_EQ(0U, ADeleter::s_callCount);
+ EXPECT_NE(nullptr, a.pointer());
+ EXPECT_EQ(0x7e89U, a.type());
+
+ auto* oldPointer = a.pointer();
+ a.setPointer(std::unique_ptr<B, ADeleter>(new B));
+ EXPECT_EQ(2U, A::s_constructorCallCount);
+ EXPECT_EQ(1U, A::s_destructorCallCount);
+ EXPECT_EQ(1U, B::s_constructorCallCount);
+ EXPECT_EQ(0U, B::s_destructorCallCount);
+ EXPECT_EQ(1U, ADeleter::s_callCount);
+ EXPECT_NE(oldPointer, a.pointer());
+ EXPECT_EQ(0x7e89U, a.type());
+
+}
+
} // namespace TestWebKitAPI