【问题标题】:why we need both std::promise and std::future?为什么我们需要 std::promise 和 std::future?
【发布时间】:2016-03-14 04:22:58
【问题描述】:

我想知道为什么我们需要 std::promise 和 std::future ?为什么 c++11 标准将 get 和 set_value 分为两个单独的类 std::future 和 std::promise? 在这个post 的回答中,它提到:

它被分成这两个独立的“接口”的原因是 对“消费者/阅读者”隐藏“写入/设置”功能。

我不明白躲在这里的好处。但是如果我们只有一个类“未来”不是更简单吗?例如:promise.set_value 可以替换成 future.set_value。

【问题讨论】:

  • 为什么你认为把它们砸在一起是个好主意?为什么有人要同时读取和写入结果?
  • 目前如果我们想从future中获取值,我们调用promise.get_future().get(),如果我们想设置值,我们调用promise.set_value()。我只是想知道我们需要额外的操作。
  • @camino 好吧,作为 T.C.也说过,没有真正的理由提供捷径来获得无论如何都应该知道的值。
  • @camino:如果您有一个承诺,那么您永远不应该成为检索价值的人。特别是因为您只能拨打get_future 一次
  • FWIW,2006 年关于 std::future 的原始提案允许设置和检索值:Peter Dimov 的 n2096 和 Howard Hinnant 的 n2094。当 future 丢失 set_value 时,是 Anthony Williams 的 n2276,但有两种替代方式来输入值:packaged_task 和 promise。

标签: c++ c++11


【解决方案1】:

promise/future 要解决的问题是将值从一个线程引导到另一个线程。它也可能会转移异常。

所以源线程必须有一些可以与之交谈的对象,以便将所需的值发送到另一个线程。好吧...谁拥有该对象?如果源有一个指向目标线程拥有的东西的指针,源如何知道目标线程是否删除了该对象?也许目标线程不再关心值;也许有些事情发生了变化,以至于它决定把你的线程放在地板上然后忘记它。

在某些情况下,这是完全合法的代码。

所以现在问题变成了为什么源不拥有承诺而只是给目标一个指向它的指针/引用?好吧,这是有充分理由的:promise 归源线程所有。一旦源线程终止,promise 将被销毁。 从而使目标线程具有对已销毁 promise 的引用。

哎呀。

因此,唯一可行的解​​决方案是拥有两个成熟的对象:一个用于源,一个用于目标。这些对象共享所转移价值的所有权。当然,这并不意味着它们不能是相同的type;你可以有类似shared_ptr<promise> 之类的东西。毕竟,promise/future 必须在内部有某种共享存储,对吗?

但是,请考虑当前的 promise/future 接口。

promise is non-copyable。您可以移动它,但不能复制它。 future 也是不可复制的,但 future 可以变成可复制的 shared_future。所以你可以有多个目的地,但只有一个来源

promise只能设置值;它甚至无法取回它。 future 只能获取值;它无法设置它。因此,您有一个非对称接口,它完全适合这个用例。您不希望目标能够设置值而源能够检索它。那是向后的代码逻辑。

所以这就是你想要两个对象的原因。您有一个非对称接口,最好使用两个相关但独立的类型和对象来处理。

【讨论】:

    【解决方案2】:

    我会将 promise/future 视为异步队列(仅用于保存单个值)。

    未来是队列的读取端。承诺是队列的写入端。

    两者的使用通常是不同的:生产者通常只是写入“队列”,而消费者只是从中读取。尽管,正如您所指出的,生产者可以读取该值,但很少有理由这样做,因此优化该特定操作很少被视为优先事项。

    在通常的方案中,生产者产生价值,并将其放入承诺中。消费者从未来获得价值。每个“客户”使用一个专门用于一项简单任务的简单界面,因此更容易设计和记录代码,并确保(例如)消费者代码不会与与产生价值相关的事情(或反之亦然)。是的,可以做到这一点,但需要做足够多的额外工作,这不太可能是偶然发生的。

    【讨论】:

      猜你喜欢
      • 2017-03-12
      • 1970-01-01
      • 1970-01-01
      • 2014-11-10
      • 2019-04-26
      • 1970-01-01
      • 2021-11-11
      • 2011-03-16
      • 2012-04-03
      相关资源
      最近更新 更多