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);
 }
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);
 }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to