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 18:14:23


Le 09/04/12 20:06, Jeffrey Lee Hellrung, Jr. a écrit :
> On Mon, Apr 9, 2012 at 10:41 AM, Vicente J. Botet Escriba
> <vicente.botet_at_[hidden] <mailto:vicente.botet_at_[hidden]>> wrote:
>
> Le 08/04/12 17:18, Jeffrey Lee Hellrung, Jr. a écrit :
>> On Sun, Apr 8, 2012 at 5:46 AM, Vicente J. Botet Escriba
>> <vicente.botet_at_[hidden] <mailto:vicente.botet_at_[hidden]>> wrote:
>>
> After the commit some error have appeared on the regression test
> (see below). It seems that the rvalue reference semantic has
> changed a lot for gcc. I will try to use the last design for this
> compiler version. Then I'll see what needs to be done for other
> compilers as soon as results appear on the regression tests page.
>
>
> TBH, I wasn't really sure exactly what problem you were trying to
> address with that patch, and how it addressed that :/ Care to recap?
>
> Note that I think we have 2 threads here on Boost.Thread, one
> regarding VS 2010 and one regarding Sun. I might be getting them confused.
>
Hi,

Sorry for all this noise.

I'm replaying to the error signaled on this thread and it concerns VS
2010 (not Sun) and concerns also other compilers (in particular I tested
the example below with clang 3.0, gcc-4.6.2,4.7.0)

The signaled error was

E:\boost_1_49\boost/thread/future.hpp(1251): error C2535:
'boost::detail::task_object<R,F>::task_object(F)' : member function
already defined or declared
           with
           [
               R=size_t,
               
F=std::tr1::_Bind<size_t,size_t,std::tr1::_Bind1<std::tr1::_Callable_fun<size_t
(__cdecl *const )(std::string &),false>,const char *>> &
           ]
           E:\boost_1_49\boost/thread/future.hpp(1247) : see declaration
of 'boost::detail::task_object<R,F>::task_object'
           with
           [
               R=size_t,
               
F=std::tr1::_Bind<size_t,size_t,std::tr1::_Bind1<std::tr1::_Callable_fun<size_t
(__cdecl *const )(std::string &),false>,const char *>> &
           ]

The concerned code is
         template<typename R,typename F>
         struct task_object:
             task_base<R>
         {
             F f;
             task_object(F const& f_):
                 f(f_)
             {}
             task_object(F&& f_):
                 f(f_)
             {}
     template<typename R>
     class packaged_task
     {
         template <class F>
         explicit packaged_task(F const& f):
             task(new detail::task_object<R,F>(f)),future_obtained(false)
         {}
         explicit packaged_task(R(*f)()):
             task(new
detail::task_object<R,R(*)()>(f)),future_obtained(false)
         {}
         template <class F>
         explicit packaged_task(F&& f):
             task(new
detail::task_object<R,F>(f)),future_obtained(false) // *** 1
         {}

I think the error comes from the following line in the example (see ***2
below)

  async_func_pt<RetType>* p= new async_func_pt<RetType>
(boost::packaged_task<RetType>(f));

that should forward the reference while passing f.

  async_func_pt<RetType>* p= new async_func_pt<RetType>
(boost::packaged_task<RetType>(std::forward<F>(f)));

because otherwise I believe the deduced template type is F&. Am I right?

When F& was given to the constructor of packaged_task it instantiated
task_object<R,F&>
As the same error were in the the Boost.Thread code in (1) above. The
use of forward solves the issue

             task(new
detail::task_object<R,F>(boost::forward<F>(f))),future_obtained(false)
// *** 1

So the instantiated constructors were

             task_object( const F& & f_):
                 f(f_)
             {}
             task_object(F& && f_):
                 f(f_)
             {}

which produced the ambiguity.

There are yet some problems on the Boost.Thread implementation or with
the compilers implementation.

When I want to pass functor, as in

A a(5);
boost::packaged_task<int> pt(a);

the constructor used is packaged_task(F&& f) and I will expect
packaged_task(F const& f) to be use for.
Are my expectations correct?

The test futures/packaged_task/alloc_ctor_pass.cpp gives this context.

Thanks for your patience and perseverance.

Best,
Vicente

P.S. I have committed the example as test_ml.cpp with some modifications.
I have rolled back the code adding the forward calls and I'll commit it
in trunk as sonn as the whole regression works on all the compiler I can
test.

======================================================
#include "boost/test/unit_test.hpp"
#include "boost/thread/future.hpp"
#include "boost/utility/result_of.hpp"
#include <functional>

struct async_func {
     virtual ~async_func() { }
     virtual void run() =0;
     };

template <typename Ret>
class async_func_pt : public async_func {
     boost::packaged_task<Ret> f;
public:
     void run() override { f(); }
     async_func_pt (boost::packaged_task<Ret>&& f) : f(std::move(f)) {}
     ~async_func_pt() { }
     boost::unique_future<Ret> get_future() { return f.get_future(); }
     };

void async_core (async_func* p);

template <typename F>
boost::unique_future<typename boost::result_of< F() >::type>
async (F&& f)
  {
  typedef typename boost::result_of< F() >::type RetType;
  async_func_pt<RetType>* p= new async_func_pt<RetType>
(boost::packaged_task<RetType>(f)); // ***2
  boost::unique_future<RetType> future_result= p->get_future();
  async_core (p);
  return std::move(future_result);
  }

template <typename F, typename A1>
boost::unique_future<typename boost::result_of< F(A1) >::type>
async (F&& f, A1&& a1)
  {
// This should be all it needs. But get a funny error deep inside Boost.
// problem overloading with && ?
  return async (std::tr1::bind(f,a1));
  }

BOOST_AUTO_TEST_SUITE(thread_pool_tests)

int calculate_the_answer_to_life_the_universe_and_everything()
{
     return 42;
}

size_t foo (const std::string& s)
  {
  return s.size();
  }

BOOST_AUTO_TEST_CASE( async_test )
{
// this one works
     // most fundimental form:
     boost::unique_future<int> fi= async
(&calculate_the_answer_to_life_the_universe_and_everything);
     int i= fi.get();
     BOOST_CHECK_EQUAL (i, 42);

// This one chokes at compile time
     boost::unique_future<size_t> fut_1= async (&foo, "Life");

     BOOST_CHECK_EQUAL (fut_1.get(), 4);
}

BOOST_AUTO_TEST_SUITE_END()



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