[PATCH] Patch for bug #17819
Marshall Clow
mclow.lists at gmail.com
Tue Apr 1 20:17:39 PDT 2014
Hi howard.hinnant,
The problem is that packaged_task uses an allocator to allocate memory for the packaged_task. If you don't pass it one, it uses std::allocator<function_type>. That's fine for functors in general, and function pointers, but not for actual functions. You can't create a std::allocator<void(int)>.
What I've done here is add a call to decay<> on the function type. This has no effect for structs, nor std::function, nor lambdas, etc, but a function will decay to a function pointer, which we can instantiate and allocator for.
http://llvm-reviews.chandlerc.com/D3258
Files:
include/future
test/thread/futures/futures.tas/futures.task.members/ctor_func.pass.cpp
test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp
Index: include/future
===================================================================
--- include/future
+++ include/future
@@ -1872,7 +1872,7 @@
__packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(_Fp&& __f)
: __f_(nullptr)
{
- typedef typename remove_reference<_Fp>::type _FR;
+ typedef typename remove_reference<typename decay<_Fp>::type>::type _FR;
typedef __packaged_task_func<_FR, allocator<_FR>, _Rp(_ArgTypes...)> _FF;
if (sizeof(_FF) <= sizeof(__buf_))
{
@@ -1897,7 +1897,7 @@
: __f_(nullptr)
{
typedef allocator_traits<_Alloc> __alloc_traits;
- typedef typename remove_reference<_Fp>::type _FR;
+ typedef typename remove_reference<typename decay<_Fp>::type>::type _FR;
typedef __packaged_task_func<_FR, _Alloc, _Rp(_ArgTypes...)> _FF;
if (sizeof(_FF) <= sizeof(__buf_))
{
Index: test/thread/futures/futures.tas/futures.task.members/ctor_func.pass.cpp
===================================================================
--- test/thread/futures/futures.tas/futures.task.members/ctor_func.pass.cpp
+++ test/thread/futures/futures.tas/futures.task.members/ctor_func.pass.cpp
@@ -35,6 +35,8 @@
int A::n_moves = 0;
int A::n_copies = 0;
+int func(int i) { return i; }
+
int main()
{
{
@@ -58,4 +60,18 @@
assert(A::n_copies > 0);
assert(A::n_moves > 0);
}
+ {
+ std::packaged_task<int(int)> p(&func);
+ assert(p.valid());
+ std::future<int> f = p.get_future();
+ p(4);
+ assert(f.get() == 4);
+ }
+ {
+ std::packaged_task<int(int)> p(func);
+ assert(p.valid());
+ std::future<int> f = p.get_future();
+ p(4);
+ assert(f.get() == 4);
+ }
}
Index: test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp
===================================================================
--- test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp
+++ test/thread/futures/futures.tas/futures.task.members/ctor_func_alloc.pass.cpp
@@ -37,6 +37,8 @@
int A::n_moves = 0;
int A::n_copies = 0;
+int func(int i) { return i; }
+
int main()
{
{
@@ -52,7 +54,7 @@
}
assert(test_alloc_base::count == 0);
A::n_copies = 0;
- A::n_copies = 0;
+ A::n_moves = 0;
{
A a(5);
std::packaged_task<double(int, char)> p(std::allocator_arg,
@@ -66,4 +68,28 @@
assert(A::n_moves > 0);
}
assert(test_alloc_base::count == 0);
+ A::n_copies = 0;
+ A::n_moves = 0;
+ {
+ A a(5);
+ std::packaged_task<int(int)> p(std::allocator_arg, test_allocator<A>(), &func);
+ assert(test_alloc_base::count > 0);
+ assert(p.valid());
+ std::future<int> f = p.get_future();
+ p(4);
+ assert(f.get() == 4);
+ }
+ assert(test_alloc_base::count == 0);
+ A::n_copies = 0;
+ A::n_moves = 0;
+ {
+ A a(5);
+ std::packaged_task<int(int)> p(std::allocator_arg, test_allocator<A>(), func);
+ assert(test_alloc_base::count > 0);
+ assert(p.valid());
+ std::future<int> f = p.get_future();
+ p(4);
+ assert(f.get() == 4);
+ }
+ assert(test_alloc_base::count == 0);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3258.1.patch
Type: text/x-patch
Size: 3246 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140401/eded5c75/attachment.bin>
More information about the cfe-commits
mailing list