Boost logo

Boost Users :

Subject: Re: [Boost-users] problems with Boost.Thread on VS10
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2012-04-09 19:24:25


On Mon, Apr 9, 2012 at 3:14 PM, Vicente J. Botet Escriba <
vicente.botet_at_[hidden]> wrote:

> 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]> 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]> 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.
>

No problem! I just want to be sure we're on the same page. I'm not very
familiar with the thread library but I thought I could contribute to this
problem in some way :/

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?
>

I think you're (partially) 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.
>

Agreed.

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?
>

Well...no, apparently your expectations are not correct. But that's
slightly beside the point. I think the correct fix here is to remove the
packaged_task(F const &) overload entirely, since the packaged_task(F&&)
overload already covers it (that's part of the entire design of "templated
rvalue references", to capture both rvalues *and* lvalues). Then
instantiate task_object with something like remove_cv<
remove_reference<F>::type >::type, and use boost::forward<F>(f) to pass the
function object down to the task_object constructor.

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!

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 mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>



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