problems with Boost.Thread on VS10
I'm trying to use a packaged_task, and get an error on creation.
template
I'm trying to use a packaged_task, and get an error on creation.
template
struct task_object: task_base<R> { F f; task_object(F const& f_): // << refers to look here f(f_) {} #ifndef BOOST_NO_RVALUE_REFERENCES task_object(F&& f_): // <<<< Error here f(f_) {} E:\boost_1_49\boost/thread/future.hpp(1251): error C2535: 'boost::detail::task_object
::task_object(F)' : member function already defined or declared with [ R=size_t, F=std::tr1::_Bind
,const char *>> & ] E:\boost_1_49\boost/thread/future.hpp(1247) : see declaration of 'boost::detail::task_object ::task_object' with [ R=size_t, F=std::tr1::_Bind
,const char *>> & ]
Can you provide a trivial example that reproduces the issue?
#include
On 4/5/2012 2:32 AM, Igor R wrote:
Can you provide a trivial example that reproduces the issue?
#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
Le 06/04/12 08:04, John M. Dlugosz a écrit :
On 4/5/2012 2:32 AM, Igor R wrote:
Can you provide a trivial example that reproduces the issue?
See below some points that don't work yet with Boost.
#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)) {}
Should't you use std::forward here?
~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
::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)); boost::unique_future<RetType> future_result= p->get_future(); async_core (p); return std::move(future_result); } template
boost::unique_future ::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)); }
I don't think std::tr1::bind manage with rvalue references. Is this the Boost version? Have you tried using std::bind?
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
fut_1= async (&foo, "Life"); BOOST_CHECK_EQUAL (fut_1.get(), 4); }
BOOST_AUTO_TEST_SUITE_END()
As you are using std::move, &&, ... why not using directly the C++11 Thread library provided with the compiler? BTW, Boost.Thread could not implement async using Boost, as Boost.Tuple, Boost.Bind Boost.Fusion (Tuple) because these libraries dont manage with rvalue references. Best, Vicente
On 4/6/2012 11:59 AM, Vicente J. Botet Escriba wrote:
As you are using std::move, &&, ... why not using directly the C++11 Thread library provided with the compiler?
1) VS10 has && and std::move, but does not have the C++11 threading library. 1b) A naive implementation (just starts a new OS thread) is not wanted. 1c) but, an overly heavy implementation is not wanted either (i.e VS11 beta), because of additional dependencies in the program to distribute. 2) In the final code, the && will be optional, to avoid copies on compilers that support it, but must work with compilers that don't. 3) I need to preserve semantics of the code I'm replacing with modern C++ forms.
BTW, Boost.Thread could not implement async using Boost, as Boost.Tuple, Boost.Bind Boost.Fusion (Tuple) because these libraries dont manage with rvalue references.
I don't understand how that applies to my compiler problem. It's telling me that task_object(F const& f_); // << refers to look here task_object(F&& f_); // <<<< Error here are not a valid overloading set and instead conflict.
Le 07/04/12 11:11, John M. Dlugosz a écrit :
On 4/6/2012 11:59 AM, Vicente J. Botet Escriba wrote:
As you are using std::move, &&, ... why not using directly the C++11 Thread library provided with the compiler?
1) VS10 has && and std::move, but does not have the C++11 threading library. 1b) A naive implementation (just starts a new OS thread) is not wanted. 1c) but, an overly heavy implementation is not wanted either (i.e VS11 beta), because of additional dependencies in the program to distribute. 2) In the final code, the && will be optional, to avoid copies on compilers that support it, but must work with compilers that don't. 3) I need to preserve semantics of the code I'm replacing with modern C++ forms. OK, I see.
BTW, Boost.Thread could not implement async using Boost, as Boost.Tuple, Boost.Bind Boost.Fusion (Tuple) because these libraries dont manage with rvalue references.
I don't understand how that applies to my compiler problem. It's telling me that
task_object(F const& f_); // << refers to look here task_object(F&& f_); // <<<< Error here
are not a valid overloading set and instead conflict.
Sorry, I misunderstood your message.
After applying the following patch your example compiles. Please could
you try it?
Could you also add a Trac ticket so that this is tracked?
HTH,
Vicente
Index: future.hpp
===================================================================
--- future.hpp (revision 77816)
+++ future.hpp (working copy)
@@ -1695,7 +1695,10 @@
task_base<R>
{
F f;
- task_object(F const& f_):
+// task_object(F const& f_):
+// f(f_)
+// {}
+ task_object(R(*f_)()):
f(f_)
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
@@ -1703,6 +1706,7 @@
f(f_)
{}
#else
+
#if defined BOOST_THREAD_USES_MOVE
task_object(boost::rv<F>& f_):
f(boost::move(f_))
@@ -1736,7 +1740,10 @@
task_base<void>
{
F f;
- task_object(F const& f_):
+// task_object(F const& f_):
+// f(f_)
+// {}
+ task_object(void(*f_)()):
f(f_)
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
@@ -1797,10 +1804,10 @@
{}
// construction and destruction
- template <class F>
- explicit packaged_task(F const& f):
- task(new detail::task_object
On Sun, Apr 8, 2012 at 5:46 AM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 07/04/12 11:11, John M. Dlugosz a écrit :
On 4/6/2012 11:59 AM, Vicente J. Botet Escriba wrote:
As you are using std::move, &&, ... why not using directly the C++11 Thread library provided with the compiler?
1) VS10 has && and std::move, but does not have the C++11 threading library. 1b) A naive implementation (just starts a new OS thread) is not wanted. 1c) but, an overly heavy implementation is not wanted either (i.e VS11 beta), because of additional dependencies in the program to distribute. 2) In the final code, the && will be optional, to avoid copies on compilers that support it, but must work with compilers that don't. 3) I need to preserve semantics of the code I'm replacing with modern C++ forms.
OK, I see.
BTW, Boost.Thread could not implement async using Boost, as Boost.Tuple, Boost.Bind Boost.Fusion (Tuple) because these libraries dont manage with rvalue references.
I don't understand how that applies to my compiler problem. It's telling me that
task_object(F const& f_); // << refers to look here task_object(F&& f_); // <<<< Error here
are not a valid overloading set and instead conflict.
Sorry, I misunderstood your message.
After applying the following patch your example compiles. Please could you try it?
Could you also add a Trac ticket so that this is tracked?
HTH, Vicente
Vicente, It looks like you're just removing the task_object::task_object(F const &) overload. Seems strange that this overload existed but was/is never actually suppose to be used. ...except when F is a function pointer, I guess??? I sent a message to the list recently observing that one problem was the binding of F to be an lvalue reference (according to the error message, AFAICS), meaning that "F const &" and "F&&" are exactly the same type. Perhaps this behavior should be addressed directly? - Jeff Index: future.hpp
==============================**==============================**======= --- future.hpp (revision 77816) +++ future.hpp (working copy) @@ -1695,7 +1695,10 @@ task_base<R> { F f; - task_object(F const& f_): +// task_object(F const& f_): +// f(f_) +// {} + task_object(R(*f_)()): f(f_) {} #ifndef BOOST_NO_RVALUE_REFERENCES @@ -1703,6 +1706,7 @@ f(f_) {} #else + #if defined BOOST_THREAD_USES_MOVE task_object(boost::rv<F>& f_): f(boost::move(f_)) @@ -1736,7 +1740,10 @@ task_base<void> { F f; - task_object(F const& f_): +// task_object(F const& f_): +// f(f_) +// {} + task_object(void(*f_)()): f(f_) {} #ifndef BOOST_NO_RVALUE_REFERENCES @@ -1797,10 +1804,10 @@ {}
// construction and destruction - template <class F> - explicit packaged_task(F const& f): - task(new detail::task_object
(f)),** future_obtained(false) - {} +// template <class F> +// explicit packaged_task(F const& f): +// task(new detail::task_object (f)),** future_obtained(false) +// {} explicit packaged_task(R(*f)()): task(new detail::task_object (** f)),future_obtained(false) {} ______________________________**_________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/**mailman/listinfo.cgi/boost-**usershttp://lists.boost.org/mailman/listinfo.cgi/boost-users
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
mailto:vicente.botet@wanadoo.fr> wrote: Le 07/04/12 11:11, John M. Dlugosz a écrit :
On 4/6/2012 11:59 AM, Vicente J. Botet Escriba wrote:
As you are using std::move, &&, ... why not using directly the C++11 Thread library provided with the compiler?
1) VS10 has && and std::move, but does not have the C++11 threading library. 1b) A naive implementation (just starts a new OS thread) is not wanted. 1c) but, an overly heavy implementation is not wanted either (i.e VS11 beta), because of additional dependencies in the program to distribute. 2) In the final code, the && will be optional, to avoid copies on compilers that support it, but must work with compilers that don't. 3) I need to preserve semantics of the code I'm replacing with modern C++ forms.
OK, I see.
BTW, Boost.Thread could not implement async using Boost, as Boost.Tuple, Boost.Bind Boost.Fusion (Tuple) because these libraries dont manage with rvalue references.
I don't understand how that applies to my compiler problem. It's telling me that
task_object(F const& f_); // << refers to look here task_object(F&& f_); // <<<< Error here
are not a valid overloading set and instead conflict.
Sorry, I misunderstood your message.
After applying the following patch your example compiles. Please could you try it?
Could you also add a Trac ticket so that this is tracked?
HTH, Vicente
Vicente,
It looks like you're just removing the task_object::task_object(F const &) overload. Seems strange that this overload existed but was/is never actually suppose to be used. ...except when F is a function pointer, I guess??? You are right. It is necessary at least when Boost.Thread uses Boost.Move. I have added it only in this case.
I sent a message to the list recently observing that one problem was the binding of F to be an lvalue reference (according to the error message, AFAICS), meaning that "F const &" and "F&&" are exactly the same type. Perhaps this behavior should be addressed directly?
Next follows the best I could reach. Please, let me know if you see
something wrong.
Thanks,
Vicente
P.S. Please don't apply this patch. I have removed some comments so it
should not be applicable as such. I will commit it soon.
svn diff boost/thread/future.hpp
Index: boost/thread/future.hpp
===================================================================
--- boost/thread/future.hpp (revision 77840)
+++ boost/thread/future.hpp (working copy)
@@ -1695,14 +1695,27 @@
task_base<R>
{
F f;
- task_object(F const& f_):
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ task_object(R(*f_)()):
f(f_)
{}
-#ifndef BOOST_NO_RVALUE_REFERENCES
task_object(F&& f_):
+ f(boost::forward<F>(f_))
+ {}
+#else
+ task_object(F const& f_):
f(f_)
{}
-#else
+
#if defined BOOST_THREAD_USES_MOVE
task_object(boost::rv<F>& f_):
f(boost::move(f_))
@@ -1736,17 +1749,29 @@
task_base<void>
{
F f;
- task_object(F const& f_):
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ task_object(void(*f_)()):
f(f_)
{}
-#ifndef BOOST_NO_RVALUE_REFERENCES
task_object(F&& f_):
+ f(boost::forward<F>(f_))
+ {}
+#else
+ task_object(F const& f_):
f(f_)
{}
-#else
#if defined BOOST_THREAD_USES_MOVE
task_object(boost::rv<F>& f_):
- f(boost::move(f_))
+ f(boost::forward<F>(f_))
{}
#else
task_object(boost::detail::thread_move_t<F> f_):
@@ -1779,6 +1804,7 @@
template<typename R>
class packaged_task
{
+ typedef boost::shared_ptr
Le 09/04/12 01:12, Vicente J. Botet Escriba a écrit :
Next follows the best I could reach. Please, let me know if you see something wrong.
Thanks, Vicente
P.S. Please don't apply this patch. I have removed some comments so it should not be applicable as such. I will commit it soon.
Committed in trunk revision 77845. Best, Vicente
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
mailto:vicente.botet@wanadoo.fr> wrote: Le 07/04/12 11:11, John M. Dlugosz a écrit :
On 4/6/2012 11:59 AM, Vicente J. Botet Escriba wrote:
As you are using std::move, &&, ... why not using directly the C++11 Thread library provided with the compiler?
1) VS10 has && and std::move, but does not have the C++11 threading library. 1b) A naive implementation (just starts a new OS thread) is not wanted. 1c) but, an overly heavy implementation is not wanted either (i.e VS11 beta), because of additional dependencies in the program to distribute. 2) In the final code, the && will be optional, to avoid copies on compilers that support it, but must work with compilers that don't. 3) I need to preserve semantics of the code I'm replacing with modern C++ forms.
OK, I see.
BTW, Boost.Thread could not implement async using Boost, as Boost.Tuple, Boost.Bind Boost.Fusion (Tuple) because these libraries dont manage with rvalue references.
I don't understand how that applies to my compiler problem. It's telling me that
task_object(F const& f_); // << refers to look here task_object(F&& f_); // <<<< Error here
are not a valid overloading set and instead conflict.
Sorry, I misunderstood your message.
After applying the following patch your example compiles. Please could you try it?
Could you also add a Trac ticket so that this is tracked?
HTH, Vicente
Vicente,
It looks like you're just removing the task_object::task_object(F const &) overload. Seems strange that this overload existed but was/is never actually suppose to be used. ...except when F is a function pointer, I guess???
I sent a message to the list recently observing that one problem was the binding of F to be an lvalue reference (according to the error message, AFAICS), meaning that "F const &" and "F&&" are exactly the same type. Perhaps this behavior should be addressed directly?
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.
Best,
Vicente
Test output: Sandia-gcc-4.3.4_0x - thread - test_4521 / gcc-4.3.4_0x
Rev 77845 / Mon, 9 Apr 2012 05:37:45 +0000
*Report Time: *Mon, 9 Apr 2012 15:38:34 +0000
Compile [2012-04-09 06:09:04 UTC]: fail
"/sierra/Sntools/extras/compilers/gcc-4.3.4/bin/g++" -ftemplate-depth-128 -std=gnu++0x -O0 -fno-inline -Wall -pedantic -g -pthread -fPIC -Wextra -Wno-long-long -pedantic -DBOOST_ALL_NO_LIB=1 -DBOOST_CHRONO_DYN_LINK=1 -DBOOST_SYSTEM_DYN_LINK=1 -DBOOST_SYSTEM_NO_DEPRECATED -DBOOST_THREAD_BUILD_DLL=1 -DBOOST_THREAD_POSIX -DBOOST_THREAD_USE_DLL=1 -I".." -c -o "/scratch/kbelco/boost/results/boost/bin.v2/libs/thread/test/test_4521.test/gcc-4.3.4_0x/debug/threading-multi/test_4521.o" "../libs/thread/test/test_4521.cpp"
../boost/thread/future.hpp: In constructor ???boost::packaged_task<R>::packaged_task(R (*)()) [with R = int]???:
../libs/thread/test/test_4521.cpp:9: instantiated from here
../boost/thread/future.hpp:1830: error: call of overloaded ???task_object(int (*&)())??? is ambiguous
../boost/thread/future.hpp:1705: note: candidates are: boost::detail::task_object
On Mon, Apr 9, 2012 at 10:41 AM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> 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@wanadoo.fr> wrote:
Le 07/04/12 11:11, John M. Dlugosz a écrit :
On 4/6/2012 11:59 AM, Vicente J. Botet Escriba wrote:
As you are using std::move, &&, ... why not using directly the C++11 Thread library provided with the compiler?
1) VS10 has && and std::move, but does not have the C++11 threading library. 1b) A naive implementation (just starts a new OS thread) is not wanted. 1c) but, an overly heavy implementation is not wanted either (i.e VS11 beta), because of additional dependencies in the program to distribute. 2) In the final code, the && will be optional, to avoid copies on compilers that support it, but must work with compilers that don't. 3) I need to preserve semantics of the code I'm replacing with modern C++ forms.
OK, I see.
BTW, Boost.Thread could not implement async using Boost, as Boost.Tuple, Boost.Bind Boost.Fusion (Tuple) because these libraries dont manage with rvalue references.
I don't understand how that applies to my compiler problem. It's telling me that
task_object(F const& f_); // << refers to look here task_object(F&& f_); // <<<< Error here
are not a valid overloading set and instead conflict.
Sorry, I misunderstood your message.
After applying the following patch your example compiles. Please could you try it?
Could you also add a Trac ticket so that this is tracked?
HTH, Vicente
Vicente,
It looks like you're just removing the task_object::task_object(F const &) overload. Seems strange that this overload existed but was/is never actually suppose to be used. ...except when F is a function pointer, I guess???
I sent a message to the list recently observing that one problem was the binding of F to be an lvalue reference (according to the error message, AFAICS), meaning that "F const &" and "F&&" are exactly the same type. Perhaps this behavior should be addressed directly?
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. [snip gcc errors] - Jeff
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
mailto:vicente.botet@wanadoo.fr> 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
mailto:vicente.botet@wanadoo.fr> 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
On Mon, Apr 9, 2012 at 3:14 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> 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@wanadoo.fr> 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@wanadoo.fr> 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
::task_object(F)' : member function already defined or declared with [ R=size_t, F=std::tr1::_Bind
,const char *>> & ] E:\boost_1_49\boost/thread/future.hpp(1247) : see declaration of 'boost::detail::task_object ::task_object' with [ R=size_t, F=std::tr1::_Bind
,const char *>> & ] The concerned code is template
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 (f)),future_obtained(false) {} explicit packaged_task(R(*f)()): task(new detail::task_object (f)),future_obtained(false) {} template <class F> explicit packaged_task(F&& f): task(new detail::task_object (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
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
(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
::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
boost::unique_future ::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
fut_1= async (&foo, "Life"); BOOST_CHECK_EQUAL (fut_1.get(), 4); }
BOOST_AUTO_TEST_SUITE_END()
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
On Mon, Apr 9, 2012 at 3:14 PM, Vicente J. Botet Escriba
mailto:vicente.botet@wanadoo.fr> wrote: 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. Yeah, this is the point. packaged_task(F const &) overload was not used never, and task_object was instantiated as task_object
. I have a
Le 10/04/12 01:24, Jeffrey Lee Hellrung, Jr. a écrit :
patch that seems to work (see below I have not used remove_cv yet, but I
agree it should be needed to take care of const functors).
The overload
explicit packaged_task(R(*f)()):
task(new
detail::task_object
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.
Thanks for all,
Vicente
iMac-de-Vicente-Botet-Escriba:trunk viboes$ svn diff boost/thread
libs/thread
Index: boost/thread/future.hpp
===================================================================
--- boost/thread/future.hpp (revision 77870)
+++ boost/thread/future.hpp (working copy)
@@ -19,6 +19,7 @@
#include
On Mon, Apr 9, 2012 at 4:54 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> 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@wanadoo.fr> wrote:
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.
Yeah, this is the point. packaged_task(F const &) overload was not used never, and task_object was instantiated as task_object
. I have a patch that seems to work (see below I have not used remove_cv yet, but I agree it should be needed to take care of const functors).
Okay, now it's starting to click what you were doing before. I might've been confusing packaged_task (where F is "free") with task_object (where F is "bound" already). I should've looked at it closer; sounds like you had already figured out the correct fix. The overload
explicit packaged_task(R(*f)()): task(new detail::task_object
(f)),future_obtained(false) {} seems necessary because otherwise the task_object is instantiated with
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. Thanks for all,
Vicente
[snip patch] Sorry for the noise, thanks for being patient, - Jeff
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
mailto:vicente.botet@wanadoo.fr> 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
mailto:vicente.botet@wanadoo.fr> wrote: The overload
explicit packaged_task(R(*f)()): task(new detail::task_object
(f)),future_obtained(false) {} seems necessary because otherwise the task_object is instantiated with
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
I just took another look at this...
On Wed, Apr 4, 2012 at 9:26 PM, John M. Dlugosz
I'm trying to use a packaged_task, and get an error on creation.
template
struct task_object: task_base<R> { F f; task_object(F const& f_): // << refers to look here f(f_) {} #ifndef BOOST_NO_RVALUE_REFERENCES task_object(F&& f_): // <<<< Error here f(f_) {} E:\boost_1_49\boost/thread/**future.hpp(1251): error C2535: 'boost::detail::task_object
::task_object(F)' : member function already defined or declared with [ R=size_t, F=std::tr1::_Bind ,const char *>> &
I think this is your problem: F is a (lvalue) reference. So F const & == F&& == F due to reference collapsing rules. ]
E:\boost_1_49\boost/thread/**future.hpp(1247) : see declaration of 'boost::detail::task_object
::task_object' with [ R=size_t, F=std::tr1::_Bind ,const char *>> & ] So I'm thinking that VS10 (Microsoft Visual Studio 2010) has problems overloading the constructor with (T const&) and (T&&) ? But shouldn't someone have noticed that long ago?
I see two ways out here. One option is to specialize task_object for reference F's. The other is to use metafunctions to choose the right parameters for the "F const &" and "F&&" constructors, respectively, e.g., use typename add_reference< typename add_const<F>::type >::type in place of "F const &" (or call_traits<F>::param_type; if you weren't looking to support C++03 you could also just use "F const &" as you are now); and use struct disabler { }; typename mpl::if_c< is_reference<F>::value, disabler, F&& >::type in place of "F&&". HTH, - Jeff
participants (4)
-
Igor R
-
Jeffrey Lee Hellrung, Jr.
-
John M. Dlugosz
-
Vicente J. Botet Escriba