diff options
author | Eric Fiselier <eric@efcs.ca> | 2014-10-23 06:24:45 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2014-10-23 06:24:45 +0000 |
commit | 83fb578e4e6f0a8c095f6e4ed0ccd7439a41c7cc (patch) | |
tree | eeb3a3f631b8d2417a03e72799e0dab5c81ba60a /libcxx | |
parent | 2ee0e9e6ee1dd2d86a2f4d4ea6bbfa5577ffe982 (diff) | |
download | bcm5719-llvm-83fb578e4e6f0a8c095f6e4ed0ccd7439a41c7cc.tar.gz bcm5719-llvm-83fb578e4e6f0a8c095f6e4ed0ccd7439a41c7cc.zip |
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
llvm-svn: 220471
Diffstat (limited to 'libcxx')
3 files changed, 98 insertions, 30 deletions
diff --git a/libcxx/include/future b/libcxx/include/future index 83513fa693d..6fe6f8da504 100644 --- a/libcxx/include/future +++ b/libcxx/include/future @@ -783,9 +783,12 @@ __assoc_state_alloc<_Rp, _Alloc>::__on_zero_shared() _NOEXCEPT { 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 _Rp, class ..._ArgTypes> 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...)>::__packaged_task_function( 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...)>::__packaged_task_function( } 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()); } } diff --git a/libcxx/test/thread/futures/futures.promise/alloc_ctor.pass.cpp b/libcxx/test/thread/futures/futures.promise/alloc_ctor.pass.cpp index 3b473508346..70a4e00b0d6 100644 --- a/libcxx/test/thread/futures/futures.promise/alloc_ctor.pass.cpp +++ b/libcxx/test/thread/futures/futures.promise/alloc_ctor.pass.cpp @@ -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()); + } } diff --git a/libcxx/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp b/libcxx/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp index 347c5cd399e..3aac2b26bfc 100644 --- a/libcxx/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp +++ b/libcxx/test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp @@ -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; } |