Le 27/06/13 22:53, Tobias Furuholm a écrit :
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.
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 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