std :: async(std :: launch :: deferred)+ std :: future :: then的行为

问题描述 投票:21回答:1

延迟未来背后的想法(仅通过使用std::async标志调用std::launch::deferred实现)是仅当有人试图等待或拉动未来的未来价值或例外时才调用回调。到那时,回调没有被执行。

如果我用std::future::then附加延期未来的延续会怎样?延迟的未来将会丢失(then使未来无效)并且会返回新的未来。

在这种情况下,根据标准,会发生什么?新的未来是一个延期的未来吗?会不会陷入僵局?最新文档中未解决此问题。

c++ concurrency c++17 stdasync std-future
1个回答
2
投票

在我看来,这似乎是the TS中的一个错误。或者至少是一个记录不足的陷阱。

以下是TS的文字:

2.3 [futures.unique_future]/6-10

template <class F>
see below then(F&& func);

要求:

INVOKE(DECAY_COPY (std::forward<F>(func)), std::move(*this)) shall be a valid expression.

功效:

该函数创建与返回的future对象关联的共享状态。另外,

当对象的共享状态准备就绪时,在未指定的执行线程上调用继续INVOKE(DECAY_COPY(std::forward<F>(func)), std::move(*this)),并在调用当时调用的线程中调用DECAY_COPY()

从continuation返回的任何值都将作为结果存储在生成的future的共享状态中。从执行延续传播的任何异常都作为异常结果存储在结果未来的共享状态中。

返回:

result_of_t<decay_t<F>(future<R>)>future<R2>时,对于某些类型R2,函数返回future<R2>。否则,该函数返回future<result_of_t<decay_t<F>(future<R>)>>。 [注意:上述规则称为隐式展开。如果没有这个规则,返回类型然后采取可调用返回future<R>将是future<future<R>>。此规则可避免此类嵌套的未来对象。下面的f2类型是future<int>而不是future<future<int>>

[例如:

future<int> f1 = g();
future<int> f2 = f1.then([](future<int> f) {
                    future<int> f3 = h();
                    return f3;
                 });

- 结束例子]

- 结束说明]

后置条件:

valid() == false关于原始未来。 valid() == true对未来的回归。 [注意:在隐式展开的情况下,从afterfunc返回的未来的有效性直到完成继续之后才能建立。如果它无效,则生成的未来将变为准备状态,但类型为std::future_error,错误条件为std::future_errc::broken_promise。 - 结束说明]

延期的未来任务没有特殊情况。如果在调用.then之前该延迟的未来任务尚未就绪,则无法使其准备就绪,因此无法调用func的衰减副本。

shared_future的文字类似;在那里,你仍然可以让shared_future在调用.then之后做好准备。

如果是这样的话; .then对未准备好的延期的独特未来将导致future的返回值永远不能准备好 - 这应该在TS /标准中明确。如果不是这样,则需要更改标准文本。

请注意,这些更改未出现在2018年发布的N4762 draft standard中。

我不确定标准应如何解决这个问题; .then语义对于shared_future是合理的,但对于future则不合适,并且不同的语义将是令人惊讶的。

© www.soinside.com 2019 - 2024. All rights reserved.