为什么boost::future::then()生成一个新线程?

时间:2021-07-06 20:57:33

When attaching a continuation to boost::future, the continuation is executed in a new thread:

当附加一个continuation to boost::future时,延续将在一个新线程中执行:

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 that, and, more importantly, is there a way to customise this behaviour? Do futures returned from promise/packaged_task/async behave differently?

为什么then()被允许这样做,更重要的是,是否有一种方法可以定制这种行为?从承诺/packaged_task/async返回的期货有不同的行为吗?

2 个解决方案

#1


3  

It is already mentioned in @ikh answer. But to make it more clear, here is the direct answer to the OP question.

在@ikh的回答中已经提到了。但为了更清楚地说明这一点,这里是OP问题的直接答案。

It is customizable whether boost::future continuation should be executed in a new thread or in the calling thread.

可以自定义boost::将来的continuation应该在新线程或调用线程中执行。

boost::launch policy parameter specifies how the continuation should run. See here: Enumeration launch

boost::启动策略参数指定延续应该如何运行。看到:枚举发射

enum class launch
{
    none = unspecified,
    async = unspecified,
    deferred = unspecified,
    executor = unspecified,
    inherit = unspecified,
    any = async | deferred
};

A future created by async(launch::deferred, ...) or ::then(launch::deferred, ...) has associated a launch policy launch::deferred.

异步创建的未来(launch: deferred,…)或:::然后(launch: deferred,…)关联了一个启动策略:::deferred。

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;        
    }
);

That should run the continuation in the same thread.
Tested with boost 1.61 + Visual Studio 2015 on Windows platform.

它应该在相同的线程中运行延续。在Windows平台上使用boost 1.61 + Visual Studio 2015进行测试。

#2


-2  

It is reasonable to spawn a new thread.. 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 spawning a new thread, we have to wait for SomeVeryVeryVeryLongLongLongLongTask() at f.then(....

没有生成一个新线程,我们必须等待SomeVeryVeryVeryLongLongLongLongTask()在f.then(....


If you want to see certain evidence? In reference,

如果你想看到某些证据?在参考,

  • 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.
  • 如果父类是使用promise< <或使用packaged_task<> (没有相关的启动策略)创建的,那么continuation的行为与第三个包含launch的策略参数的重载相同:::async | launch::deferred以及func的相同参数。

As you know, if we use launch::async | launch::deferred, we don't know whether a new thread is spawned or just it's deferred. But mostly a new thread is spawned, right?

如您所知,如果我们使用launch::async |启动::延迟,我们不知道是否生成了新线程,或者只是延迟了。但大多数情况下都是新线程生成的,对吧?

PS. Um? reference say "...promise<<...". Maybe it's a mistype of promise<> >o<

PS。嗯?参考说“…< <承诺…”。可能是承诺的错误类型<> >o<

PS2. see @sehe's replies. Strictly speaking, he's right.

PS2。看到@sehe答道。严格地说,他是对的。

#1


3  

It is already mentioned in @ikh answer. But to make it more clear, here is the direct answer to the OP question.

在@ikh的回答中已经提到了。但为了更清楚地说明这一点,这里是OP问题的直接答案。

It is customizable whether boost::future continuation should be executed in a new thread or in the calling thread.

可以自定义boost::将来的continuation应该在新线程或调用线程中执行。

boost::launch policy parameter specifies how the continuation should run. See here: Enumeration launch

boost::启动策略参数指定延续应该如何运行。看到:枚举发射

enum class launch
{
    none = unspecified,
    async = unspecified,
    deferred = unspecified,
    executor = unspecified,
    inherit = unspecified,
    any = async | deferred
};

A future created by async(launch::deferred, ...) or ::then(launch::deferred, ...) has associated a launch policy launch::deferred.

异步创建的未来(launch: deferred,…)或:::然后(launch: deferred,…)关联了一个启动策略:::deferred。

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;        
    }
);

That should run the continuation in the same thread.
Tested with boost 1.61 + Visual Studio 2015 on Windows platform.

它应该在相同的线程中运行延续。在Windows平台上使用boost 1.61 + Visual Studio 2015进行测试。

#2


-2  

It is reasonable to spawn a new thread.. 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 spawning a new thread, we have to wait for SomeVeryVeryVeryLongLongLongLongTask() at f.then(....

没有生成一个新线程,我们必须等待SomeVeryVeryVeryLongLongLongLongTask()在f.then(....


If you want to see certain evidence? In reference,

如果你想看到某些证据?在参考,

  • 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.
  • 如果父类是使用promise< <或使用packaged_task<> (没有相关的启动策略)创建的,那么continuation的行为与第三个包含launch的策略参数的重载相同:::async | launch::deferred以及func的相同参数。

As you know, if we use launch::async | launch::deferred, we don't know whether a new thread is spawned or just it's deferred. But mostly a new thread is spawned, right?

如您所知,如果我们使用launch::async |启动::延迟,我们不知道是否生成了新线程,或者只是延迟了。但大多数情况下都是新线程生成的,对吧?

PS. Um? reference say "...promise<<...". Maybe it's a mistype of promise<> >o<

PS。嗯?参考说“…< <承诺…”。可能是承诺的错误类型<> >o<

PS2. see @sehe's replies. Strictly speaking, he's right.

PS2。看到@sehe答道。严格地说,他是对的。