[libcxx] r271449 - Implement P0033R1 - Re-enabling shared_from_this

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 1 17:15:35 PDT 2016


Author: ericwf
Date: Wed Jun  1 19:15:35 2016
New Revision: 271449

URL: http://llvm.org/viewvc/llvm-project?rev=271449&view=rev
Log:
Implement P0033R1 - Re-enabling shared_from_this

Summary: See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0033r1.html

Reviewers: mclow.lists

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D19254

Modified:
    libcxx/trunk/include/memory
    libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp
    libcxx/trunk/www/cxx1z_status.html

Modified: libcxx/trunk/include/memory
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=271449&r1=271448&r2=271449&view=diff
==============================================================================
--- libcxx/trunk/include/memory (original)
+++ libcxx/trunk/include/memory Wed Jun  1 19:15:35 2016
@@ -4120,7 +4120,7 @@ private:
         void
         __enable_weak_this(const enable_shared_from_this<_Yp>* __e) _NOEXCEPT
         {
-            if (__e)
+            if (__e && __e->__weak_this_.expired())
             {
                 __e->__weak_this_.__ptr_ = const_cast<_Yp*>(static_cast<const _Yp*>(__e));
                 __e->__weak_this_.__cntrl_ = __cntrl_;
@@ -5432,6 +5432,16 @@ public:
     shared_ptr<_Tp const> shared_from_this() const
         {return shared_ptr<const _Tp>(__weak_this_);}
 
+#if _LIBCPP_STD_VER > 14
+    _LIBCPP_INLINE_VISIBILITY
+    weak_ptr<_Tp> weak_from_this() _NOEXCEPT
+       { return __weak_this_; }
+
+    _LIBCPP_INLINE_VISIBILITY
+    weak_ptr<const _Tp> weak_from_this() const _NOEXCEPT
+        { return __weak_this_; }
+#endif // _LIBCPP_STD_VER > 14
+
     template <class _Up> friend class shared_ptr;
 };
 

Modified: libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp?rev=271449&r1=271448&r2=271449&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp Wed Jun  1 19:15:35 2016
@@ -18,11 +18,15 @@
 // public:
 //     shared_ptr<T> shared_from_this();
 //     shared_ptr<T const> shared_from_this() const;
+//     weak_ptr<T> weak_from_this() noexcept;                         // C++17
+//     weak_ptr<T const> weak_from_this() const noexecpt;             // C++17
 // };
 
 #include <memory>
 #include <cassert>
 
+#include "test_macros.h"
+
 struct T
     : public std::enable_shared_from_this<T>
 {
@@ -32,6 +36,8 @@ struct Y : T {};
 
 struct Z : Y {};
 
+void nullDeleter(void*) {}
+
 int main()
 {
     {  // https://llvm.org/bugs/show_bug.cgi?id=18843
@@ -50,4 +56,84 @@ int main()
     assert(p == q);
     assert(!p.owner_before(q) && !q.owner_before(p)); // p and q share ownership
     }
+    // Test LWG issue 2529. Only reset '__weak_ptr_' when it's already expired.
+    // http://cplusplus.github.io/LWG/lwg-active.html#2529.
+    // Test two different ways:
+    // * Using 'weak_from_this().expired()' in C++17.
+    // * Using 'shared_from_this()' in all dialects.
+    {
+
+        T* ptr = new T;
+        std::shared_ptr<T> s(ptr);
+        {
+            // Don't re-initialize the "enabled_shared_from_this" base
+            // because it already references a non-expired shared_ptr.
+            std::shared_ptr<T> s2(ptr, &nullDeleter);
+        }
+#if TEST_STD_VER > 14
+        // The enabled_shared_from_this base should still be referencing
+        // the original shared_ptr.
+        assert(!ptr->weak_from_this().expired());
+#endif
+#ifndef TEST_HAS_NO_EXCEPTIONS
+        {
+            try {
+                std::shared_ptr<T> new_s = ptr->shared_from_this();
+                assert(new_s == s);
+            } catch (std::bad_weak_ptr const&) {
+                assert(false);
+            } catch (...) {
+                assert(false);
+            }
+        }
+#endif
+    }
+    // Test LWG issue 2529 again. This time check that an expired pointer
+    // is replaced.
+    {
+        T* ptr = new T;
+        std::weak_ptr<T> weak;
+        {
+            std::shared_ptr<T> s(ptr, &nullDeleter);
+            assert(ptr->shared_from_this() == s);
+            weak = s;
+            assert(!weak.expired());
+        }
+        assert(weak.expired());
+        weak.reset();
+#ifndef TEST_HAS_NO_EXCEPTIONS
+        try {
+            ptr->shared_from_this();
+            assert(false);
+        } catch (std::bad_weak_ptr const&) {
+        } catch (...) { assert(false); }
+#endif
+        {
+            std::shared_ptr<T> s2(ptr, &nullDeleter);
+            assert(ptr->shared_from_this() == s2);
+        }
+        delete ptr;
+    }
+    // Test weak_from_this_methods
+#if TEST_STD_VER > 14
+    {
+        T* ptr = new T;
+        const T* cptr = ptr;
+
+        static_assert(noexcept(ptr->weak_from_this()), "Operation must be noexcept");
+        static_assert(noexcept(cptr->weak_from_this()), "Operation must be noexcept");
+
+        std::weak_ptr<T> my_weak = ptr->weak_from_this();
+        assert(my_weak.expired());
+
+        std::weak_ptr<T const> my_const_weak = cptr->weak_from_this();
+        assert(my_const_weak.expired());
+
+        // Enable shared_from_this with ptr.
+        std::shared_ptr<T> sptr(ptr);
+        my_weak = ptr->weak_from_this();
+        assert(!my_weak.expired());
+        assert(my_weak.lock().get() == ptr);
+    }
+#endif
 }

Modified: libcxx/trunk/www/cxx1z_status.html
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/www/cxx1z_status.html?rev=271449&r1=271448&r2=271449&view=diff
==============================================================================
--- libcxx/trunk/www/cxx1z_status.html (original)
+++ libcxx/trunk/www/cxx1z_status.html Wed Jun  1 19:15:35 2016
@@ -82,7 +82,7 @@
 	<tr><td><a href="http://wg21.link/P0226R1">P0226R1</a></td><td>LWG</td><td>Mathematical Special Functions for C++17</td><td>Jacksonville</td><td></td><td></td></tr>
 	<tr><td><a href="http://wg21.link/P0220R1">P0220R1</a></td><td>LWG</td><td>Adopt Library Fundamentals V1 TS Components for C++17</td><td>Jacksonville</td><td></td><td></td></tr>
 	<tr><td><a href="http://wg21.link/P0218R1">P0218R1</a></td><td>LWG</td><td>Adopt the File System TS for C++17</td><td>Jacksonville</td><td></td><td></td></tr>	
-	<tr><td><a href="http://wg21.link/P0033R1">P0033R1</a></td><td>LWG</td><td>Re-enabling shared_from_this</td><td>Jacksonville</td><td></td><td></td></tr>
+	<tr><td><a href="http://wg21.link/P0033R1">P0033R1</a></td><td>LWG</td><td>Re-enabling shared_from_this</td><td>Jacksonville</td><td>Complete</td><td>3.9</td></tr>
 	<tr><td><a href="http://wg21.link/P0005R4">P0005R4</a></td><td>LWG</td><td>Adopt not_fn from Library Fundamentals 2 for C++17</td><td>Jacksonville</td><td></td><td></td></tr>
 	<tr><td><a href="http://wg21.link/P0152R1">P0152R1</a></td><td>LWG</td><td>constexpr atomic::is_always_lock_free</td><td>Jacksonville</td><td>Complete</td><td>3.9</td></tr>
 	<tr><td><a href="http://wg21.link/P0185R1">P0185R1</a></td><td>LWG</td><td>Adding [nothrow-]swappable traits</td><td>Jacksonville</td><td>Complete</td><td>3.9</td></tr>




More information about the cfe-commits mailing list