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 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@220471 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4e7d53664d
commit
4d2413ca4b
include
test/thread/futures
@ -783,9 +783,12 @@ __assoc_state_alloc<_Rp, _Alloc>::__on_zero_shared() _NOEXCEPT
|
|||||||
{
|
{
|
||||||
if (this->__state_ & base::__constructed)
|
if (this->__state_ & base::__constructed)
|
||||||
reinterpret_cast<_Rp*>(_VSTD::addressof(this->__value_))->~_Rp();
|
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();
|
this->~__assoc_state_alloc();
|
||||||
__a.deallocate(this, 1);
|
__a.deallocate(_PTraits::pointer_to(*this), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Rp, class _Alloc>
|
template <class _Rp, class _Alloc>
|
||||||
@ -806,9 +809,12 @@ template <class _Rp, class _Alloc>
|
|||||||
void
|
void
|
||||||
__assoc_state_alloc<_Rp&, _Alloc>::__on_zero_shared() _NOEXCEPT
|
__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();
|
this->~__assoc_state_alloc();
|
||||||
__a.deallocate(this, 1);
|
__a.deallocate(_PTraits::pointer_to(*this), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Alloc>
|
template <class _Alloc>
|
||||||
@ -829,9 +835,12 @@ template <class _Alloc>
|
|||||||
void
|
void
|
||||||
__assoc_sub_state_alloc<_Alloc>::__on_zero_shared() _NOEXCEPT
|
__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();
|
this->~__assoc_sub_state_alloc();
|
||||||
__a.deallocate(this, 1);
|
__a.deallocate(_PTraits::pointer_to(*this), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Rp, class _Fp>
|
template <class _Rp, class _Fp>
|
||||||
@ -1414,12 +1423,13 @@ template <class _Rp>
|
|||||||
template <class _Alloc>
|
template <class _Alloc>
|
||||||
promise<_Rp>::promise(allocator_arg_t, const _Alloc& __a0)
|
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;
|
typedef __allocator_destructor<_A2> _D2;
|
||||||
_A2 __a(__a0);
|
_A2 __a(__a0);
|
||||||
unique_ptr<__assoc_state_alloc<_Rp, _Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
|
unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1));
|
||||||
::new(__hold.get()) __assoc_state_alloc<_Rp, _Alloc>(__a0);
|
::new(static_cast<void*>(_VSTD::addressof(*__hold.get()))) _State(__a0);
|
||||||
__state_ = __hold.release();
|
__state_ = _VSTD::addressof(*__hold.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Rp>
|
template <class _Rp>
|
||||||
@ -1587,12 +1597,13 @@ template <class _Rp>
|
|||||||
template <class _Alloc>
|
template <class _Alloc>
|
||||||
promise<_Rp&>::promise(allocator_arg_t, const _Alloc& __a0)
|
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;
|
typedef __allocator_destructor<_A2> _D2;
|
||||||
_A2 __a(__a0);
|
_A2 __a(__a0);
|
||||||
unique_ptr<__assoc_state_alloc<_Rp&, _Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
|
unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1));
|
||||||
::new(__hold.get()) __assoc_state_alloc<_Rp&, _Alloc>(__a0);
|
::new(static_cast<void*>(_VSTD::addressof(*__hold.get()))) _State(__a0);
|
||||||
__state_ = __hold.release();
|
__state_ = _VSTD::addressof(*__hold.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Rp>
|
template <class _Rp>
|
||||||
@ -1723,12 +1734,13 @@ public:
|
|||||||
template <class _Alloc>
|
template <class _Alloc>
|
||||||
promise<void>::promise(allocator_arg_t, const _Alloc& __a0)
|
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;
|
typedef __allocator_destructor<_A2> _D2;
|
||||||
_A2 __a(__a0);
|
_A2 __a(__a0);
|
||||||
unique_ptr<__assoc_sub_state_alloc<_Alloc>, _D2> __hold(__a.allocate(1), _D2(__a, 1));
|
unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1));
|
||||||
::new(__hold.get()) __assoc_sub_state_alloc<_Alloc>(__a0);
|
::new(static_cast<void*>(_VSTD::addressof(*__hold.get()))) _State(__a0);
|
||||||
__state_ = __hold.release();
|
__state_ = _VSTD::addressof(*__hold.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Rp>
|
template <class _Rp>
|
||||||
@ -1808,10 +1820,12 @@ template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes>
|
|||||||
void
|
void
|
||||||
__packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate()
|
__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());
|
_Ap __a(__f_.second());
|
||||||
__f_.~__compressed_pair<_Fp, _Alloc>();
|
__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>
|
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)
|
allocator_arg_t, const _Alloc& __a0, _Fp&& __f)
|
||||||
: __f_(nullptr)
|
: __f_(nullptr)
|
||||||
{
|
{
|
||||||
typedef allocator_traits<_Alloc> __alloc_traits;
|
|
||||||
typedef typename remove_reference<typename decay<_Fp>::type>::type _FR;
|
typedef typename remove_reference<typename decay<_Fp>::type>::type _FR;
|
||||||
typedef __packaged_task_func<_FR, _Alloc, _Rp(_ArgTypes...)> _FF;
|
typedef __packaged_task_func<_FR, _Alloc, _Rp(_ArgTypes...)> _FF;
|
||||||
if (sizeof(_FF) <= sizeof(__buf_))
|
if (sizeof(_FF) <= sizeof(__buf_))
|
||||||
@ -1910,18 +1923,13 @@ __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
typedef typename __alloc_traits::template
|
typedef typename __allocator_traits_rebind<_Alloc, _FF>::type _Ap;
|
||||||
#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
|
|
||||||
rebind_alloc<_FF>
|
|
||||||
#else
|
|
||||||
rebind_alloc<_FF>::other
|
|
||||||
#endif
|
|
||||||
_Ap;
|
|
||||||
_Ap __a(__a0);
|
_Ap __a(__a0);
|
||||||
typedef __allocator_destructor<_Ap> _Dp;
|
typedef __allocator_destructor<_Ap> _Dp;
|
||||||
unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
|
unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
|
||||||
::new (__hold.get()) _FF(_VSTD::forward<_Fp>(__f), _Alloc(__a));
|
::new (static_cast<void*>(_VSTD::addressof(*__hold.get())))
|
||||||
__f_ = __hold.release();
|
_FF(_VSTD::forward<_Fp>(__f), _Alloc(__a));
|
||||||
|
__f_ = _VSTD::addressof(*__hold.release());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "../test_allocator.h"
|
#include "../test_allocator.h"
|
||||||
|
#include "min_allocator.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
@ -48,4 +49,36 @@ int main()
|
|||||||
assert(f.valid());
|
assert(f.valid());
|
||||||
}
|
}
|
||||||
assert(test_alloc_base::count == 0);
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "../../test_allocator.h"
|
#include "../../test_allocator.h"
|
||||||
|
#include "min_allocator.h"
|
||||||
|
|
||||||
class A
|
class A
|
||||||
{
|
{
|
||||||
@ -94,4 +95,30 @@ int main()
|
|||||||
assert(f.get() == 4);
|
assert(f.get() == 4);
|
||||||
}
|
}
|
||||||
assert(test_alloc_base::count == 0);
|
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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user