Boost logo

Boost Users :

Subject: Re: [Boost-users] problems with Boost.Thread on VS10
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2012-04-09 21:31:45


Le 10/04/12 02:10, Jeffrey Lee Hellrung, Jr. a écrit :
> On Mon, Apr 9, 2012 at 4:54 PM, Vicente J. Botet Escriba
> <vicente.botet_at_[hidden] <mailto:vicente.botet_at_[hidden]>> wrote:
>
> Le 10/04/12 01:24, Jeffrey Lee Hellrung, Jr. a écrit :
>> On Mon, Apr 9, 2012 at 3:14 PM, Vicente J. Botet Escriba
>> <vicente.botet_at_[hidden] <mailto:vicente.botet_at_[hidden]>> wrote:
>>
>>
>>
>>
> The overload
>
> explicit packaged_task(R(*f)()):
> task(new
> detail::task_object<R,R(*)()>(f)),future_obtained(false)
> {}
>
> seems necessary because otherwise the task_object is instantiated
> with <R,R()> which is not what we want.
> Do you have an hint on how simplify this?
>
>
> Okay yeah I wasn't sure why you needed this overload, thanks for
> clarifying. I guess when constructing a packaged_task with a function
> name, and you don't explicitly use the address-of operator (&), F gets
> bound as a function reference? Probably easiest to just explicitly use
> a separate constructor as above and document its necessity.
>
>>
>> The test futures/packaged_task/alloc_ctor_pass.cpp gives this
>> context.
>>
>> Thanks for your patience and perseverance.
>>
>>
>> And thank you for clarifying the issue for me!
>>
>>
> Please, could you check the patch and see if there is something
> that can be improved.
>
>
> Yeah that looks about what I would've suggested. Just add, like you
> said, the remove_cv's.
>

I have added some test for const and free functions.

Note, as you mentioned, the need to use & in (***1) when the function
doesn't returns the packaged_task result type but something convertible
to it.

With the following patch everything is OK.

It is a pleasure to work with you. I learn always something important :-)
Vicente

===============================================
tests
===============================================

double fct()
{
   return 5.0;
}
long lfct()
{
   return 5;
}

   {
       const A a(5);
       boost::packaged_task<double> p(a);
       BOOST_TEST(p.valid());
       boost::future<double> f = BOOST_EXPLICIT_MOVE(p.get_future());
       //p(3, 'a');
       p();
       BOOST_TEST(f.get() == 5.0);
       BOOST_TEST(A::n_copies > 0);
       BOOST_TEST(A::n_moves > 0);
   }
   {
       boost::packaged_task<double> p(fct);
       BOOST_TEST(p.valid());
       boost::future<double> f = BOOST_EXPLICIT_MOVE(p.get_future());
       //p(3, 'a');
       p();
       BOOST_TEST(f.get() == 5.0);
   }
   {
       boost::packaged_task<double> p(&lfct); // *** 1
       BOOST_TEST(p.valid());
       boost::future<double> f = BOOST_EXPLICIT_MOVE(p.get_future());
       //p(3, 'a');
       p();
       BOOST_TEST(f.get() == 5.0);
   }

===============================================
patch
===============================================

Index: boost/thread/future.hpp
===================================================================
--- boost/thread/future.hpp (revision 77875)
+++ boost/thread/future.hpp (working copy)
@@ -20,6 +20,7 @@
  #include <boost/type_traits/is_fundamental.hpp>
  #include <boost/type_traits/is_convertible.hpp>
  #include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/remove_cv.hpp>
  #include <boost/mpl/if.hpp>
  #include <boost/config.hpp>
  #include <boost/throw_exception.hpp>
@@ -1811,7 +1812,9 @@
  #ifndef BOOST_NO_RVALUE_REFERENCES
          template <class F>
          explicit packaged_task(F&& f):
- task(new detail::task_object<R,typename
remove_reference<F>::type>(boost::forward<F>(f))),future_obtained(false)
+ task(new detail::task_object<R,
+ typename remove_cv<typename
remove_reference<F>::type>::type
+ >(boost::forward<F>(f))),future_obtained(false)
          {}
  #else
          template <class F>
@@ -1832,11 +1835,22 @@
  #endif

  #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
+ template <class Allocator>
+ packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
+ {
+ typedef R(*FR)();
+ typedef typename Allocator::template
rebind<detail::task_object<R,FR> >::other A2;
+ A2 a2(a);
+ typedef thread_detail::allocator_destructor<A2> D;
+
+ task = task_ptr(::new(a2.allocate(1))
detail::task_object<R,FR>(f), D(a2, 1) );
+ future_obtained = false;
+ }
  #ifndef BOOST_NO_RVALUE_REFERENCES
          template <class F, class Allocator>
          packaged_task(boost::allocator_arg_t, Allocator a, F&& f)
          {
- typedef typename remove_reference<F>::type FR;
+ typedef typename remove_cv<typename
remove_reference<F>::type>::type FR;
            typedef typename Allocator::template
rebind<detail::task_object<R,FR> >::other A2;
            A2 a2(a);
            typedef thread_detail::allocator_destructor<A2> D;



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net