Why does boost :: future <T> :: then () spawn a new thread?
When attaching a continuation to boost::future continuation is executed in a new thread:
std::cout << "main: " << boost::this_thread::get_id() << std::endl; boost::promise<void> p; boost::future<void> f = p.get_future(); p.set_value(); boost::future<void> f2 = f.then([] (boost::future<void>) { std::cout << "future: " << boost::this_thread::get_id() << std::endl; }); This snippet outputs:
main: 0x7fff7a8d7310 future: 0x101781000 Why is .then() allowed to do this, and more importantly, is there a way to tweak this behavior? Do future returns from promise / packaged_task / async behave differently?
This has already been mentioned in the @ikh answer. But to make this clearer, here is a direct answer to the OP question.
You can configure whether to continue boost::future in the new thread or in the calling thread.
boost::launch policy setting specifies how the continuation should continue. See Here: Starting an Enumeration
enum class launch { none = unspecified, async = unspecified, deferred = unspecified, executor = unspecified, inherit = unspecified, any = async | deferred }; The future created by
async(launch::deferred, ...)or::then(launch::deferred, ...)is related to thelaunch::deferredpolicy.
So try running this:
boost::future<void> f2 = f.then( boost::launch::deferred, [] (boost::future<void>&&) { std::cout << "future: " << boost::this_thread::get_id() << std::endl; } ); This should continue in the same thread.
Tested with a boost of 1.61 + Visual Studio 2015 on the Windows platform.
It is wise to create a new thread. Take a look at this code:
std::cout << "main: " << boost::this_thread::get_id() << std::endl; boost::promise<void> p; boost::future<void> f = p.get_future(); p.set_value(); boost::future<void> f2 = f.then([] (boost::future<void>) { SomeVeryVeryVeryLongLongLongLongTask(); std::cout << "future: " << boost::this_thread::get_id() << std::endl; }); Without creating a new thread, we must wait for SomeVeryVeryVeryLongLongLongLongTask() in f.then(...
If you want to see certain evidence? In reference ,
- If the parent was created with the promise <<or with packaging_task <> (does not have an associated launch policy), the continuation behaves the same as the third overload with the launch :: async | run :: delayed same argument for func.
As you know, if we use launch::async | launch::deferred launch::async | launch::deferred , we donβt know if a new thread is being generated or just being delayed. But basically a new thread is created, right?
PS. Mm? the link says "... promise <<...". This is probably the wrong type of promise<> >> o <
PS2. see @sehe answers. Strictly speaking, he is right.