Opened 9 years ago
Closed 9 years ago
#9303 closed Bugs (worksforme)
packaged_task<R(Argtypes)> does not compile using c++03 and Cmake 2.8.9
Reported by: | Owned by: | viboes | |
---|---|---|---|
Milestone: | Component: | thread | |
Version: | Boost 1.54.0 | Severity: | Problem |
Keywords: | packaged_task, bind, asio | Cc: |
Description
Setup consists of client(s), a server, and device(s).
A client interacts with a device by sending requests to the server. These requests are examined and routed to the appropriate device. Requests are handled asynchronously, and are occasionally queued up via boost::asio::io_service::strand for various reasons.
It appears as if packaged_task has a few different templates to choose from:
packaged_task<R> packaged_task<R()> packaged_task<R(ArgTypes)>
To ensure that I was using the function correctly, I started simple; using the simple example on the boost::futures page as a starting point. From there, I created four simple functions:
int return, no parameters. int return, with parameters. std::string return, no parameters. std::string return, with parameters. Test functions
std::string ans("forty two"); int int_no_params() { return 42; } int int_with_params(int param) { return param; } std::string string_no_params() { return std::string("forty two"); } std::string string_with_params(std::string & param) // Have tried both with and without '&' { return param; }
EXAMPLE 1:
int function(void) //! Compiles and produces correct result. { boost::packaged_task<int()> example(int_no_params); boost::future<int> f = example.get_future(); boost::thread task(boost::move(example)); int answer = f.get(); std::cout << "Answer to life and whatnot, in English: " << answer << std::endl; task.join(); }
EXAMPLE 2:
std::string function(void) //! Compiles and produces correct result. { boost::packaged_task<std::string()> example(string_no_params); boost::future<std::string> f = example.get_future(); boost::thread task(boost::move(example)); std::string answer = f.get(); std::cout << "string_no_params: " << answer << std::endl; task.join(); }
EXAMPLE 3:
std::string(std::string& param) No threading //! Doesn't compile. //! error: variable ‘boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)> example’ has initializer but incomplete type { boost::packaged_task<std::string(std::string&)> example(string_with_params); boost::future<std::string> f = example.get_future(); example(ans); std::string answer = f.get(); std::cout << "string_with_params: " << answer << std::endl; }
EXAMPLE 4:
using boost::threading //! Doesn't compile. //! error: variable ‘boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)> example’ has initializer but incomplete type { boost::packaged_task<std::string(std::string&)> example(string_with_params); boost::future<std::string> f = example.get_future(); boost::thread task(boost::move(example), ans); std::string answer = f.get(); std::cout << "string_with_params: " << answer << std::endl; task.join(); }
EXAMPLE 5:
//Using extended initializers in packaged_task declaration //! Doesn't compile in C++03, C++11 only. //! error: extended initializer lists only available with -std=c++11 or -std=gnu++11 [-Werror] { boost::packaged_task<std::string(std::string&)> example { boost::bind(&string_with_params, ans) }; boost::future<std::string> f = example.get_future(); boost::thread task(boost::move(example), ans); std::string answer = f.get(); std::cout << "string_with_params: " << answer << std::endl; task.join(); }
EXAMPLE 6:
//Threaded, using shared_ptr //The following use typedef boost::packaged_task<std::string(std::string&)> task_t; //Because packaged tasks can't be copied, binding //shared_ptr<T>::operator() to task was a suggested solution found on stackoverflow. // error: invalid use of incomplete type ‘class boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>’ // error: incomplete type ‘task_t {aka boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>}’ used in nested name specifier // boost/thread/future.hpp:1320:11: error: declaration of ‘class boost::packaged_task<std::basic_string<char>(std::basic_string<char>&)>’ { boost::shared_ptr<task_t> example = boost::make_shared<task_t>(boost::bind(&string_with_params, ans)); boost::future<std::string> f = example->get_future(); boost::thread task(boost::bind(&task_t::operator(), example)); std::string answer = f.get(); std::cout << "string_with_params: " << answer << std::endl; task.join(); }
EXAMPLE 7:
//Using boost::asio::io_service and boost::bind // error: invalid use of incomplete type ‘class boost::packaged_task(std::basic_string&)>’ // error: incomplete type ‘task_t {aka boost::packaged_task(std::basic_string&)>}’ used in nested name specifier // boost/thread/future.hpp:1320:11: error: declaration of ‘class boost::packaged_task(std::basic_string&)>’ { boost::asio::io_service io_service; boost::thread_group threads; boost::asio::io_service::work work(io_service); for (int i = 0; i < 3; ++i) { threads.create_thread(boost::bind(&boost::asio::io_service::run, &io_service)); } boost::shared_ptr<task_t> example = boost::make_shared<task_t>(boost::bind(&string_with_params, ans)); boost::future<std::string> f = example->get_future(); io_service.post(boost::bind(&task_t::operator(), example)); std::string answer = f.get(); std::cout << "string_with_params: " << answer << std::endl; threads.join_all(); }
It seems like future.hpp has a problem that is preventing the proper template from being used.
Attachments (1)
Change History (8)
by , 9 years ago
Attachment: | packagedTestTest.cpp added |
---|
comment:1 by , 9 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:2 by , 9 years ago
I'm sorry, I thought I included the compiler information in the ticket.
Our build(s) use CMake 2.8.8, and gcc 4.6 (with some variance depending on system).
We are using BOOST_THREAD_VERSION = 4.
comment:3 by , 9 years ago
I'm really sorry. This doesn't works yet for non C++98 compilers. Here it is the code
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) template<typename R, typename ...ArgTypes> class packaged_task<R(ArgTypes...)> { typedef boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task_ptr; boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task; #else template<typename R> class packaged_task<R()> { typedef boost::shared_ptr<detail::task_base_shared_state<R()> > task_ptr; boost::shared_ptr<detail::task_base_shared_state<R()> > task; #endif
As you can see, only if BOOST_THREAD_PROVIDES_VARIADIC_THREAD you can use
boost::packaged_task<std::string(std::string&)>
I'm not sure Example 5 is a bug on Boost.Thread, I suspect that this is just not supported in C++03.
Unfortunately I have no time to develop this for C++03 compilers.
comment:4 by , 9 years ago
Anyway, I have tried to compile your example with C++11 and there are some issues. I will take a deeper look.
The line in example 6 seems suspect
boost::thread task(boost::bind(&task_t::operator(), example));
comment:5 by , 9 years ago
This doesn't solves the issues,but I missed this code
svn diff future.hpp Index: future.hpp =================================================================== --- future.hpp (revision 86540) +++ future.hpp (working copy) @@ -2766,12 +2766,18 @@ private: task_shared_state(task_shared_state&); public: +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + R (*f)(BOOST_THREAD_RV_REF(ArgTypes) ... ); + task_shared_state(R (*f_)(BOOST_THREAD_RV_REF(ArgTypes) ... )): + f(f_) + {} +#else R (*f)(); task_shared_state(R (*f_)()): f(f_) {} +#endif - #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) { @@ -2848,12 +2854,18 @@ private: task_shared_state(task_shared_state&); public: +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + R& (*f)(BOOST_THREAD_RV_REF(ArgTypes) ... ); + task_shared_state(R& (*f_)(BOOST_THREAD_RV_REF(ArgTypes) ... )): + f(f_) + {} +#else R& (*f)(); task_shared_state(R& (*f_)()): f(f_) {} +#endif - #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) {
comment:6 by , 9 years ago
Hi and sorry for the delay.
You need to use boost::ref() while passing by reference
boost::thread task(boost::move(example), boost::ref(ans));
comment:7 by , 9 years ago
Milestone: | To Be Determined |
---|---|
Resolution: | → worksforme |
Status: | assigned → closed |
Committed the examples with the fixes
https://github.com/boostorg/thread/commit/7d4f485ade79c0fbb6434402e52045040ef000c9
This is normal if you are using BOOST_THREAD_VERSION = 2, which is the default.
If you can not use BOOST_THREAD_VERSION = 2, use packaged_task<R> instead of packaged_task<R()>, but you couldn't work with non-nullary functions (you must then use boost::bind).
Which version are you using? Which compiler?