|
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