[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