[libcxx] r220471 - Add support for "fancy" pointers to promise and packaged_task.

Eric Fiselier eric at efcs.ca
Wed Oct 22 23:24:46 PDT 2014


Author: ericwf
Date: Thu Oct 23 01:24:45 2014
New Revision: 220471

URL: http://llvm.org/viewvc/llvm-project?rev=220471&view=rev
Log:
Add support for "fancy" pointers to promise and packaged_task.

Summary:
This patch is very closely related to D4859. Please see http://reviews.llvm.org/D4859 for more information.

This patch adds support for "fancy" pointers and allocators to promise and packaged_task. The changes made to support this are exactly the same as in D4859.



Test Plan: "fancy" pointer tests were added to each constructor affected by the change.

Reviewers: danalbert, mclow.lists

Reviewed By: mclow.lists

Subscribers: cfe-commits

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

Modified:
    libcxx/trunk/include/future
    libcxx/trunk/test/thread/futures/futures.promise/alloc_ctor.pass.cpp
    libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp

Modified: libcxx/trunk/include/future
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/future?rev=220471&r1=220470&r2=220471&view=diff
==============================================================================
--- libcxx/trunk/include/future (original)
+++ libcxx/trunk/include/future Thu Oct 23 01:24:45 2014
@@ -783,9 +783,12 @@ __assoc_state_alloc<_Rp, _Alloc>::__on_z
 {
     if (this->__state_ & base::__constructed)
         reinterpret_cast<_Rp*>(_VSTD::addressof(this->__value_))->~_Rp();
-    typename _Alloc::template rebind<__assoc_state_alloc>::other __a(__alloc_);
+    typedef typename __allocator_traits_rebind<_Alloc, __assoc_state_alloc>::type _A;
+    typedef allocator_traits<_A> _ATraits;
+    typedef pointer_traits<typename _ATraits::pointer> _PTraits;
+    _A __a(__alloc_);
     this->~__assoc_state_alloc();
-    __a.deallocate(this, 1);
+    __a.deallocate(_PTraits::pointer_to(*this), 1);
 }
 
 template <class _Rp, class _Alloc>
@@ -806,9 +809,12 @@ template <class _Rp, class _Alloc>
 void
 __assoc_state_alloc<_Rp&, _Alloc>::__on_zero_shared() _NOEXCEPT
 {
-    typename _Alloc::template rebind<__assoc_state_alloc>::other __a(__alloc_);
+    typedef typename __allocator_traits_rebind<_Alloc, __assoc_state_alloc>::type _A;
+    typedef allocator_traits<_A> _ATraits;
+    typedef pointer_traits<typename _ATraits::pointer> _PTraits;
+    _A __a(__alloc_);
     this->~__assoc_state_alloc();
-    __a.deallocate(this, 1);
+    __a.deallocate(_PTraits::pointer_to(*this), 1);
 }
 
 template <class _Alloc>
@@ -829,9 +835,12 @@ template <class _Alloc>
 void
 __assoc_sub_state_alloc<_Alloc>::__on_zero_shared() _NOEXCEPT
 {
-    typename _Alloc::template rebind<__assoc_sub_state_alloc>::other __a(__alloc_);
+    typedef typename __allocator_traits_rebind<_Alloc, __assoc_sub_state_alloc>::type _A;
+    typedef allocator_traits<_A> _ATraits;
+    typedef pointer_traits<typename _ATraits::pointer> _PTraits;
+    _A __a(__alloc_);
     this->~__assoc_sub_state_alloc();
-    __a.deallocate(this, 1);
+    __a.deallocate(_PTraits::pointer_to(*this), 1);
 }
 
 template <class _Rp, class _Fp>
@@ -1414,12 +1423,13 @@ template <class _Rp>
 template <class _Alloc>
 promise<_Rp>::promise(allocator_arg_t, const _Alloc& __a0)
 {
-    typedef typename _Alloc::template rebind<__assoc_state_alloc<_Rp, _Alloc> >::other _A2;
+    typedef __assoc_state_alloc<_Rp, _Alloc> _State;
+    typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2;
     typedef __allocator_destructor<_A2> _D2;
     _A2 __a(__a0);
-    unique_ptr<__assoc_state_alloc<_Rp, _Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
-    ::new(__hold.get()) __assoc_state_alloc<_Rp, _Alloc>(__a0);
-    __state_ = __hold.release();
+    unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1));
+    ::new(static_cast<void*>(_VSTD::addressof(*__hold.get()))) _State(__a0);
+    __state_ = _VSTD::addressof(*__hold.release());
 }
 
 template <class _Rp>
@@ -1587,12 +1597,13 @@ template <class _Rp>
 template <class _Alloc>
 promise<_Rp&>::promise(allocator_arg_t, const _Alloc& __a0)
 {
-    typedef typename _Alloc::template rebind<__assoc_state_alloc<_Rp&, _Alloc> >::other _A2;
+    typedef __assoc_state_alloc<_Rp&, _Alloc> _State;
+    typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2;
     typedef __allocator_destructor<_A2> _D2;
     _A2 __a(__a0);
-    unique_ptr<__assoc_state_alloc<_Rp&, _Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
-    ::new(__hold.get()) __assoc_state_alloc<_Rp&, _Alloc>(__a0);
-    __state_ = __hold.release();
+    unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1));
+    ::new(static_cast<void*>(_VSTD::addressof(*__hold.get()))) _State(__a0);
+    __state_ = _VSTD::addressof(*__hold.release());
 }
 
 template <class _Rp>
@@ -1723,12 +1734,13 @@ public:
 template <class _Alloc>
 promise<void>::promise(allocator_arg_t, const _Alloc& __a0)
 {
-    typedef typename _Alloc::template rebind<__assoc_sub_state_alloc<_Alloc> >::other _A2;
+    typedef __assoc_sub_state_alloc<_Alloc> _State;
+    typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2;
     typedef __allocator_destructor<_A2> _D2;
     _A2 __a(__a0);
-    unique_ptr<__assoc_sub_state_alloc<_Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
-    ::new(__hold.get()) __assoc_sub_state_alloc<_Alloc>(__a0);
-    __state_ = __hold.release();
+    unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1));
+    ::new(static_cast<void*>(_VSTD::addressof(*__hold.get()))) _State(__a0);
+    __state_ = _VSTD::addressof(*__hold.release());
 }
 
 template <class _Rp>
@@ -1808,10 +1820,12 @@ template<class _Fp, class _Alloc, class
 void
 __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate()
 {
-    typedef typename _Alloc::template rebind<__packaged_task_func>::other _Ap;
+    typedef typename __allocator_traits_rebind<_Alloc, __packaged_task_func>::type _Ap;
+    typedef allocator_traits<_Ap> _ATraits;
+    typedef pointer_traits<typename _ATraits::pointer> _PTraits;
     _Ap __a(__f_.second());
     __f_.~__compressed_pair<_Fp, _Alloc>();
-    __a.deallocate(this, 1);
+    __a.deallocate(_PTraits::pointer_to(*this), 1);
 }
 
 template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes>
@@ -1900,7 +1914,6 @@ __packaged_task_function<_Rp(_ArgTypes..
                                   allocator_arg_t, const _Alloc& __a0, _Fp&& __f)
     : __f_(nullptr)
 {
-    typedef allocator_traits<_Alloc> __alloc_traits;
     typedef typename remove_reference<typename decay<_Fp>::type>::type _FR;
     typedef __packaged_task_func<_FR, _Alloc, _Rp(_ArgTypes...)> _FF;
     if (sizeof(_FF) <= sizeof(__buf_))
@@ -1910,18 +1923,13 @@ __packaged_task_function<_Rp(_ArgTypes..
     }
     else
     {
-        typedef typename __alloc_traits::template
-#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
-            rebind_alloc<_FF>
-#else
-            rebind_alloc<_FF>::other
-#endif
-                                                     _Ap;
+        typedef typename __allocator_traits_rebind<_Alloc, _FF>::type _Ap;
         _Ap __a(__a0);
         typedef __allocator_destructor<_Ap> _Dp;
         unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
-        ::new (__hold.get()) _FF(_VSTD::forward<_Fp>(__f), _Alloc(__a));
-        __f_ = __hold.release();
+        ::new (static_cast<void*>(_VSTD::addressof(*__hold.get())))
+            _FF(_VSTD::forward<_Fp>(__f), _Alloc(__a));
+        __f_ = _VSTD::addressof(*__hold.release());
     }
 }
 

Modified: libcxx/trunk/test/thread/futures/futures.promise/alloc_ctor.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.promise/alloc_ctor.pass.cpp?rev=220471&r1=220470&r2=220471&view=diff
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.promise/alloc_ctor.pass.cpp (original)
+++ libcxx/trunk/test/thread/futures/futures.promise/alloc_ctor.pass.cpp Thu Oct 23 01:24:45 2014
@@ -20,6 +20,7 @@
 #include <cassert>
 
 #include "../test_allocator.h"
+#include "min_allocator.h"
 
 int main()
 {
@@ -48,4 +49,36 @@ int main()
         assert(f.valid());
     }
     assert(test_alloc_base::count == 0);
+    // Test with a minimal allocator
+    {
+        std::promise<int> p(std::allocator_arg, bare_allocator<void>());
+        std::future<int> f = p.get_future();
+        assert(f.valid());
+    }
+    {
+        std::promise<int&> p(std::allocator_arg, bare_allocator<void>());
+        std::future<int&> f = p.get_future();
+        assert(f.valid());
+    }
+    {
+        std::promise<void> p(std::allocator_arg, bare_allocator<void>());
+        std::future<void> f = p.get_future();
+        assert(f.valid());
+    }
+    // Test with a minimal allocator that returns class-type pointers
+    {
+        std::promise<int> p(std::allocator_arg, min_allocator<void>());
+        std::future<int> f = p.get_future();
+        assert(f.valid());
+    }
+    {
+        std::promise<int&> p(std::allocator_arg, min_allocator<void>());
+        std::future<int&> f = p.get_future();
+        assert(f.valid());
+    }
+    {
+        std::promise<void> p(std::allocator_arg, min_allocator<void>());
+        std::future<void> f = p.get_future();
+        assert(f.valid());
+    }
 }

Modified: libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp?rev=220471&r1=220470&r2=220471&view=diff
==============================================================================
--- libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp (original)
+++ libcxx/trunk/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp Thu Oct 23 01:24:45 2014
@@ -20,6 +20,7 @@
 #include <cassert>
 
 #include "../../test_allocator.h"
+#include "min_allocator.h"
 
 class A
 {
@@ -94,4 +95,30 @@ int main()
         assert(f.get() == 4);
     }
     assert(test_alloc_base::count == 0);
+    A::n_copies = 0;
+    A::n_moves  = 0;
+    {
+        std::packaged_task<double(int, char)> p(std::allocator_arg,
+                                                bare_allocator<void>(), A(5));
+        assert(p.valid());
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+        assert(A::n_copies == 0);
+        assert(A::n_moves > 0);
+    }
+    A::n_copies = 0;
+    A::n_moves  = 0;
+    {
+        std::packaged_task<double(int, char)> p(std::allocator_arg,
+                                                min_allocator<void>(), A(5));
+        assert(p.valid());
+        std::future<double> f = p.get_future();
+        p(3, 'a');
+        assert(f.get() == 105.0);
+        assert(A::n_copies == 0);
+        assert(A::n_moves > 0);
+    }
+    A::n_copies = 0;
+    A::n_moves  = 0;
 }





More information about the cfe-commits mailing list