future<>.then and promises
I am trying out future<>.then and I am seeing some results that confuses me. I have tried to illustrate this with a few examples. The first example is using a promise together with future<>.then. It generates no output: boost::promise<int> promise; boost::future<int> fut = promise.get_future(); promise.set_value(123); fut.then([](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); }); boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration); Why is fut.then not triggered? (assigning fut.then to another future makes no difference) By adding a launch policy I get the output "The value is: 123" which is the output I would expect from all my examples: boost::promise<int> promise; boost::future<int> fut = promise.get_future(); promise.set_value(123); fut.then(boost::launch::async, [](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); }); boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration); To make this more real, let's move promise.set_value to after .then boost::promise<int> promise; boost::future<int> fut = promise.get_future(); fut.then(boost::launch::async, [](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); }); promise.set_value(123); boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration); This program outputs nothing and never terminates. But when I assign the result of fut.then to another future I get the expected output once again: boost::promise<int> promise; boost::future<int> fut = promise.get_future(); boost::future<int> fut2 = fut.then(boost::launch::async, [](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); }); promise.set_value(123); boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration); Finally, as I bonus I add an example where I use async to generate a future instead. boost::future<int> fut = boost::async([]() { return 123; }); fut.then([](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); }); boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration); This generates the output "The value is: " (without 123). Once again, by assigning the result of fut.then to another future I get the expected output. I use boost 1.54 beta 1 with clang 3.2 on Linux and. /Tobias
Le 27/06/13 14:26, Tobias Furuholm a écrit :
I am trying out future<>.then and I am seeing some results that confuses me. I have tried to illustrate this with a few examples. The first example is using a promise together with future<>.then. It generates no output:
boost::promise<int> promise; boost::future<int> fut = promise.get_future(); promise.set_value(123);
fut.then([](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration);
Why is fut.then not triggered? (assigning fut.then to another future makes no difference) I guess you need to call fut.then() before the value is set. I will need to check if this works when the future is not created with async().
By adding a launch policy I get the output "The value is: 123" which is the output I would expect from all my examples:
boost::promise<int> promise; boost::future<int> fut = promise.get_future();
promise.set_value(123);
fut.then(boost::launch::async, [](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration);
Could you tell me the version of BOOST_THREAD_VERSION are you using?
To make this more real, let's move promise.set_value to after .then
boost::promise<int> promise; boost::future<int> fut = promise.get_future();
fut.then(boost::launch::async, [](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
promise.set_value(123);
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration);
This program outputs nothing and never terminates. But when I assign the result of fut.then to another future I get the expected output once again:
boost::promise<int> promise; boost::future<int> fut = promise.get_future();
boost::future<int> fut2 = fut.then(boost::launch::async, [](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
promise.set_value(123);
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration);
Where is the assignment? Again I will need to check this.
Finally, as I bonus I add an example where I use async to generate a future instead.
boost::future<int> fut = boost::async([]() { return 123; });
fut.then([](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration);
future::get() can be called only once depending on the value of BOOST_THREAD_VERSION
This generates the output "The value is: " (without 123). Once again, by assigning the result of fut.then to another future I get the expected output.
I use boost 1.54 beta 1 with clang 3.2 on Linux and.
Please, could you provide complete examples, and the command line? Best, Vicente
On Thu, Jun 27, 2013 at 9:01 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 27/06/13 14:26, Tobias Furuholm a écrit :
I am trying out future<>.then and I am seeing some results that confuses
me. I have tried to illustrate this with a few examples. The first example is using a promise together with future<>.then. It generates no output:
boost::promise<int> promise; boost::future<int> fut = promise.get_future(); promise.set_value(123);
fut.then([](boost::future<int>**& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(**duration);
Why is fut.then not triggered? (assigning fut.then to another future makes no difference)
I guess you need to call fut.then() before the value is set. I will need to check if this works when the future is not created with async().
It makes no difference.
By adding a launch policy I get the output "The value is: 123" which is the output I would expect from all my examples:
boost::promise<int> promise; boost::future<int> fut = promise.get_future();
promise.set_value(123);
fut.then(boost::launch::async, [](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(**duration);
Could you tell me the version of BOOST_THREAD_VERSION are you using?
I use BOOST_THREAD_VERSION=4
To make this more real, let's move promise.set_value to after .then
boost::promise<int> promise; boost::future<int> fut = promise.get_future();
fut.then(boost::launch::async, [](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
promise.set_value(123);
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(**duration);
This program outputs nothing and never terminates. But when I assign the result of fut.then to another future I get the expected output once again:
boost::promise<int> promise; boost::future<int> fut = promise.get_future();
*boost::future<int> fut2* = fut.then(boost::launch::async, [](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
promise.set_value(123);
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(**duration);
Where is the assignment?
I made the assignment bold to make it more visible...
Again I will need to check this.
Finally, as I bonus I add an example where I use async to generate a
future instead.
boost::future<int> fut = boost::async([]() { return 123; });
fut.then([](boost::future<int>**& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(**duration);
future::get() can be called only once depending on the value of BOOST_THREAD_VERSION
This generates the output "The value is: " (without 123). Once again, by
assigning the result of fut.then to another future I get the expected output.
I use boost 1.54 beta 1 with clang 3.2 on Linux and.
Please, could you provide complete examples, and the command line?
The examples are complete except for includes and that they are put in a main function. So e.g. the first example looks like this when complete #include <boost/thread.hpp> int main() { boost::promise<int> promise; boost::future<int> fut = promise.get_future(); promise.set_value(123); fut.then([](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); }); boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration); } The command line follows: clang++ -m32 --std=c++11 -DBOOST_THREAD_VERSION=4 -I/usr/local/boost_1_54_0_beta1 -I/usr/include/x86_64-linux-gnu/c++/4.7/32 main.cpp -pthread -o test -L/usr/local/boost_1_54_0_beta1/stage/lib -lboost_system -lboost_thread The -m32 is because I build for a 32-bit target on a 64 bit machine. Boost is also compiled with 32-bit. Regards, Tobias
On Thu, Jun 27, 2013 at 9:01 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr <mailto:vicente.botet@wanadoo.fr>> wrote:
Le 27/06/13 14:26, Tobias Furuholm a écrit :
I am trying out future<>.then and I am seeing some results that confuses me. I have tried to illustrate this with a few examples. The first example is using a promise together with future<>.then. It generates no output:
boost::promise<int> promise; boost::future<int> fut = promise.get_future(); promise.set_value(123);
fut.then([](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration);
Why is fut.then not triggered? (assigning fut.then to another future makes no difference)
I guess you need to call fut.then() before the value is set. I will need to check if this works when the future is not created with async().
It makes no difference. Sorry I was wrong. There is an issue with the current implementation. If the parent future has not been created with async, you need to add the launch policy on
Le 27/06/13 22:53, Tobias Furuholm a écrit : the then call. Please, could you add a ticket to the Trac system? I will try to fix it soon.
By adding a launch policy I get the output "The value is: 123" which is the output I would expect from all my examples:
boost::promise<int> promise; boost::future<int> fut = promise.get_future();
promise.set_value(123);
fut.then(boost::launch::async, [](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration);
Could you tell me the version of BOOST_THREAD_VERSION are you using?
I use BOOST_THREAD_VERSION=4
To make this more real, let's move promise.set_value to after .then
boost::promise<int> promise; boost::future<int> fut = promise.get_future();
fut.then(boost::launch::async, [](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
promise.set_value(123);
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration);
This program outputs nothing and never terminates. But when I assign the result of fut.then to another future I get the expected output once again:
boost::promise<int> promise; boost::future<int> fut = promise.get_future();
*boost::future<int> fut2* = fut.then(boost::launch::async, [](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
promise.set_value(123);
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration);
Where is the assignment?
I made the assignment bold to make it more visible...
When you use a policy launch::async the resulting future will block on the destructor. When there is no assignment the temporary is destroyed before the promise is set.
Again I will need to check this.
Finally, as I bonus I add an example where I use async to generate a future instead.
boost::future<int> fut = boost::async([]() { return 123; });
fut.then([](boost::future<int>& f) { std::cout << "The value is: " << f.get() << std::endl; return f.get(); });
boost::chrono::milliseconds duration(1000); boost::this_thread::sleep_for(duration);
future::get() can be called only once depending on the value of BOOST_THREAD_VERSION
This generates the output "The value is: " (without 123). Once again, by assigning the result of fut.then to another future I get the expected output.
As the fut shared state is set asynchronously the temporary ends by been set, so the trace is done. Thanks, Vicente
On Thu, Jun 27, 2013 at 9:01 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
I guess you need to call fut.then() before the value is set. I will need to check if this works when the future is not created with async().
::then<<lambda_f0fec0502a034b6d05aaa9610f9b705e> >' : not all control
If the callback isn't called when set using then() if the value is already acquired, I don't see the point of then(). Between the time you retrieve a future from any function returning it and the time you call then(), the value could have been set. So I expect ft.then( task ) to call immediately task if the value have already been set. Or maybe I didn't understood correctly what you meant? On a related topic: I just upgraded to the latest SVN and forced Boost to use decltype as result_of, which fixed a problem already mentionned. Just in case it is not already known: 1. ft.then( []( future<T> f ) { return 42; } ); This will not compile (VS2012U3) because there is an attempt to copy future<T> (which looks like a bug I reported where returning a future would trigger copy instead of moving the future, bug fixed since then so I'm a bit surprise about this one) 2. ft.then( []( future<T>& f ) { return 42; } ); This trigger the following warning: 1>e:\projects\sdk\boost\boost\include\boost-1_54\boost\thread\future.hpp(3956): warning C4715: 'boost::future<aosd::backend::Id<aosd::backend::Project> paths return a value Indeed the then() implementation have a series of if-else ending with an else with assert false forced. The compiler can't catch the assertion I suppose something have to be written there after the assertion to silence the warning. Joel Lamotte
Le 28/06/13 01:45, Klaim - Joël Lamotte a écrit :
On Thu, Jun 27, 2013 at 9:01 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr <mailto:vicente.botet@wanadoo.fr>> wrote:
I guess you need to call fut.then() before the value is set. I will need to check if this works when the future is not created with async().
If the callback isn't called when set using then() if the value is already acquired, I don't see the point of then(). Between the time you retrieve a future from any function returning it and the time you call then(), the value could have been set. So I expect ft.then( task ) to call immediately task if the value have already been set.
Sorry, I was wrong and there is an issue with the implementation. When I fix it, the continuation would not be called immediately but as the doc states it should "- If the parent was created with |promise<<| or with a |packaged_task<>| (has no associated launch policy), the continuation behaves the same as the third overload with a policy argument of |launch::async | launch::deferred| and the same argument for func. "
Or maybe I didn't understood correctly what you meant?
On a related topic: I just upgraded to the latest SVN and forced Boost to use decltype as result_of, which fixed a problem already mentionned. Just in case it is not already known:
1.
ft.then( []( future<T> f ) { return 42; } );
This will not compile (VS2012U3) because there is an attempt to copy future<T> (which looks like a bug I reported where returning a future would trigger copy instead of moving the future, bug fixed since then so I'm a bit surprise about this one)
Currently the prototype of a continuation takes a future by reference, but I could change it to by value (which need to move the future.
2. ft.then( []( future<T>& f ) { return 42; } );
This trigger the following warning:
::then<<lambda_f0fec0502a034b6d05aaa9610f9b705e> >' : not all control
1>e:\projects\sdk\boost\boost\include\boost-1_54\boost\thread\future.hpp(3956): warning C4715: 'boost::future<aosd::backend::Id<aosd::backend::Project> paths return a value
Indeed the then() implementation have a series of if-else ending with an else with assert false forced. The compiler can't catch the assertion I suppose something have to be written there after the assertion to silence the warning.
This is associate to the issue of the current implementation. Instead of asserting the code should be return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( lock, *this, boost::forward<F>(func) ); Best, Vcente
On Fri, Jun 28, 2013 at 7:48 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
When I fix it, the continuation would not be called immediately but as the doc states it should
"- If the parent was created with promise<< or with a packaged_task<>(has no associated launch policy), the continuation behaves the same as the third overload with a policy argument of launch::async | launch::deferredand the same argument for func. "
Ah yes, ok, so it will be called at least when future.get() will be called, if I understood correctly?
1.
ft.then( []( future<T> f ) { return 42; } );
This will not compile (VS2012U3) because there is an attempt to copy future<T> (which looks like a bug I reported where returning a future would trigger copy instead of moving the future, bug fixed since then so I'm a bit surprise about this one)
Currently the prototype of a continuation takes a future by reference, but I could change it to by value (which need to move the future.
I thought the original standard proposition was moving the future into the callback, or is this point under discussion? Joel Lamotte
Le 28/06/13 20:39, Klaim - Joël Lamotte a écrit :
On Fri, Jun 28, 2013 at 7:48 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr <mailto:vicente.botet@wanadoo.fr>> wrote:
When I fix it, the continuation would not be called immediately but as the doc states it should
"- If the parent was created with |promise<<| or with a |packaged_task<>| (has no associated launch policy), the continuation behaves the same as the third overload with a policy argument of |launch::async | launch::deferred| and the same argument for func. "
Ah yes, ok, so it will be called at least when future.get() will be called, if I understood correctly?
Yes.
1.
ft.then( []( future<T> f ) { return 42; } );
This will not compile (VS2012U3) because there is an attempt to copy future<T> (which looks like a bug I reported where returning a future would trigger copy instead of moving the future, bug fixed since then so I'm a bit surprise about this one)
Currently the prototype of a continuation takes a future by reference, but I could change it to by value (which need to move the future.
I thought the original standard proposition was moving the future into the callback, or is this point under discussion?
You are right. I will fix this soon. best, Vicente
participants (3)
-
Klaim - Joël Lamotte
-
Tobias Furuholm
-
Vicente J. Botet Escriba