Allow assigning WeakPtr<Derived> to WeakPtr<Base>
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Oct 2017 18:48:57 +0000 (18:48 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Oct 2017 18:48:57 +0000 (18:48 +0000)
https://bugs.webkit.org/show_bug.cgi?id=177817

Reviewed by Geoff Garen.

Source/WTF:

Add templated copy/move constructors/assignment operators, similar to RefPtr.

* wtf/WeakPtr.h:
(WTF::WeakPtrFactory::createWeakPtr const):
(WTF::weak_reference_upcast):
(WTF::weak_reference_downcast):
(WTF::WeakPtr<T>::WeakPtr):
(WTF::=):
(WTF::makeWeakPtr):

Tools:

* TestWebKitAPI/Tests/WTF/WeakPtr.cpp:
(TestWebKitAPI::Base::weakPtrFactory):
(TestWebKitAPI::TEST):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@222793 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WTF/ChangeLog
Source/WTF/wtf/WeakPtr.h
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp

index 2289415..c233abd 100644 (file)
@@ -1,3 +1,20 @@
+2017-10-03  Antti Koivisto  <antti@apple.com>
+
+        Allow assigning WeakPtr<Derived> to WeakPtr<Base>
+        https://bugs.webkit.org/show_bug.cgi?id=177817
+
+        Reviewed by Geoff Garen.
+
+        Add templated copy/move constructors/assignment operators, similar to RefPtr.
+
+        * wtf/WeakPtr.h:
+        (WTF::WeakPtrFactory::createWeakPtr const):
+        (WTF::weak_reference_upcast):
+        (WTF::weak_reference_downcast):
+        (WTF::WeakPtr<T>::WeakPtr):
+        (WTF::=):
+        (WTF::makeWeakPtr):
+
 2017-10-03  JF Bastien  <jfbastien@apple.com>
 
         WebAssembly: no VM / JS version of everything but Instance
index 1377113..baf07c9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2013 Google, Inc. All Rights Reserved.
- * Copyright (C) 2015 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2015, 2017 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -61,6 +61,9 @@ private:
     T* m_ptr;
 };
 
+template<typename T, typename U> WeakReference<T>* weak_reference_upcast(WeakReference<U>*);
+template<typename T, typename U> WeakReference<T>* weak_reference_downcast(WeakReference<U>*);
+
 template<typename T>
 class WeakPtr {
     WTF_MAKE_FAST_ALLOCATED;
@@ -68,11 +71,15 @@ public:
     WeakPtr() { }
     WeakPtr(std::nullptr_t) { }
     WeakPtr(Ref<WeakReference<T>>&& ref) : m_ref(std::forward<Ref<WeakReference<T>>>(ref)) { }
+    template<typename U> WeakPtr(const WeakPtr<U>&);
+    template<typename U> WeakPtr(WeakPtr<U>&&);
 
     T* get() const { return m_ref ? m_ref->get() : nullptr; }
     operator bool() const { return m_ref && m_ref->get(); }
 
     WeakPtr& operator=(std::nullptr_t) { m_ref = nullptr; return *this; }
+    template<typename U> WeakPtr& operator=(const WeakPtr<U>&);
+    template<typename U> WeakPtr& operator=(WeakPtr<U>&&);
 
     T* operator->() const { return m_ref->get(); }
     T& operator*() const { return *m_ref->get(); }
@@ -80,6 +87,8 @@ public:
     void clear() { m_ref = nullptr; }
 
 private:
+    template<typename U> friend class WeakPtr;
+
     RefPtr<WeakReference<T>> m_ref;
 };
 
@@ -101,9 +110,7 @@ public:
     {
         if (!m_ref)
             m_ref = WeakReference<T>::create(&ptr);
-        ASSERT(&ptr == m_ref->get());
-        static_assert(std::is_convertible<U*, T*>::value, "T* must be convertible to U*");
-        return WeakPtr<U>(Ref<WeakReference<U>>(reinterpret_cast<WeakReference<U>&>(*m_ref)));
+        return { makeRef(*weak_reference_downcast<U>(m_ref.get())) };
     }
 
     void revokeAll()
@@ -119,12 +126,46 @@ private:
     mutable RefPtr<WeakReference<T>> m_ref;
 };
 
-template <typename T> inline WeakPtr<T> makeWeakPtr(T& ref)
+template<typename T, typename U> inline WeakReference<T>* weak_reference_upcast(WeakReference<U>* weakReference)
+{
+    static_assert(std::is_convertible<U*, T*>::value, "U* must be convertible to T*");
+    return reinterpret_cast<WeakReference<T>*>(weakReference);
+}
+
+template<typename T, typename U> inline WeakReference<T>* weak_reference_downcast(WeakReference<U>* weakReference)
+{
+    static_assert(std::is_convertible<T*, U*>::value, "T* must be convertible to U*");
+    return reinterpret_cast<WeakReference<T>*>(weakReference);
+}
+
+template<typename T> template<typename U> inline WeakPtr<T>::WeakPtr(const WeakPtr<U>& o)
+    : m_ref(weak_reference_upcast<T>(o.m_ref.get()))
+{
+}
+
+template<typename T> template<typename U> inline WeakPtr<T>::WeakPtr(WeakPtr<U>&& o)
+    : m_ref(adoptRef(weak_reference_upcast<T>(o.m_ref.leakRef())))
+{
+}
+
+template<typename T> template<typename U> inline WeakPtr<T>& WeakPtr<T>::operator=(const WeakPtr<U>& o)
+{
+    m_ref = weak_reference_upcast<T>(o.m_ref.get());
+    return *this;
+}
+
+template<typename T> template<typename U> inline WeakPtr<T>& WeakPtr<T>::operator=(WeakPtr<U>&& o)
+{
+    m_ref = adoptRef(weak_reference_upcast<T>(o.m_ref.leakRef()));
+    return *this;
+}
+
+template<typename T> inline WeakPtr<T> makeWeakPtr(T& ref)
 {
     return ref.weakPtrFactory().template createWeakPtr<T>(ref);
 }
 
-template <typename T> inline WeakPtr<T> makeWeakPtr(T* ptr)
+template<typename T> inline WeakPtr<T> makeWeakPtr(T* ptr)
 {
     if (!ptr)
         return { };
index 8f2f7b0..28d36eb 100644 (file)
@@ -1,3 +1,14 @@
+2017-10-03  Antti Koivisto  <antti@apple.com>
+
+        Allow assigning WeakPtr<Derived> to WeakPtr<Base>
+        https://bugs.webkit.org/show_bug.cgi?id=177817
+
+        Reviewed by Geoff Garen.
+
+        * TestWebKitAPI/Tests/WTF/WeakPtr.cpp:
+        (TestWebKitAPI::Base::weakPtrFactory):
+        (TestWebKitAPI::TEST):
+
 2017-10-03  Youenn Fablet  <youenn@apple.com>
 
         Remove no longer needed WebRTC build infrastructure
index 7a9acf5..c6d26c9 100644 (file)
@@ -212,6 +212,8 @@ public:
         return m_weakPtrFactory.createWeakPtr<T>(*this);
     }
 
+    auto& weakPtrFactory() { return m_weakPtrFactory; }
+
 private:
     WeakPtrFactory<Base> m_weakPtrFactory;
 };
@@ -254,4 +256,38 @@ TEST(WTF_WeakPtr, Downcasting)
     EXPECT_NULL(derivedWeakPtr.get());
 }
 
+TEST(WTF_WeakPtr, DerivedConstructAndAssign)
+{
+    Derived derived;
+    {
+        WeakPtr<Derived> derivedWeakPtr = makeWeakPtr(derived);
+        WeakPtr<Base> baseWeakPtr { WTFMove(derivedWeakPtr) };
+        EXPECT_EQ(baseWeakPtr.get(), &derived);
+        EXPECT_NULL(derivedWeakPtr.get());
+    }
+
+    {
+        WeakPtr<Derived> derivedWeakPtr = makeWeakPtr(derived);
+        WeakPtr<Base> baseWeakPtr { derivedWeakPtr };
+        EXPECT_EQ(baseWeakPtr.get(), &derived);
+        EXPECT_EQ(derivedWeakPtr.get(), &derived);
+    }
+
+    {
+        WeakPtr<Derived> derivedWeakPtr = makeWeakPtr(derived);
+        WeakPtr<Base> baseWeakPtr;
+        baseWeakPtr = WTFMove(derivedWeakPtr);
+        EXPECT_EQ(baseWeakPtr.get(), &derived);
+        EXPECT_NULL(derivedWeakPtr.get());
+    }
+
+    {
+        WeakPtr<Derived> derivedWeakPtr = makeWeakPtr(derived);
+        WeakPtr<Base> baseWeakPtr;
+        baseWeakPtr = derivedWeakPtr;
+        EXPECT_EQ(baseWeakPtr.get(), &derived);
+        EXPECT_EQ(derivedWeakPtr.get(), &derived);
+    }
+}
+
 } // namespace TestWebKitAPI