1

我想知道如何使用承诺和期货开发异步 API。该应用程序正在使用单个数据流,该数据流用于主动提供的周期性数据和请求/回复通信。

对于请求/回复阻塞,直到收到回复不是一个选项,我不想使用回调乱扔代码,所以我想编写某种接受预期回复的 id 并退出的 SendMessage仅在接收时。由来电者阅读回复。

候选 API 可以是:

std::future<void> sendMessage(Message msg, id expected)
{
   // Write the message
   auto promise = make_shared<std::promise<void>>();
   // Memorize the promise somewhere accessible to the receiving thread
   return promise->get_future();
 }

接收到消息的工作线程应该能够查询数据结构以了解是否有人在等待它并“释放”未来。

鉴于承诺不可重用,我想了解的是我应该使用什么样的数据结构来管理“飞行中”的承诺。

4

1 回答 1

2

此答案已被改写。

设置共享标志的状态可以使工作人员知道对方,比如老板,是否仍在期待结果。

共享标志以及承诺和未来可以包含在一个类(模板)中,比如请求。老板通过破坏他的请求副本来设置标志。工人通过在他自己的请求副本上调用某些成员函数来查询老板是否仍然期望请求完成。

标志上的同时读/写应该可能是同步的。

老板可能无法获得承诺,工人可能无法获得未来。

请求最多应该有两个副本,因为在销毁请求对象时会设置标志。为此,我们可以将相应的成员函数定义为deleteor private,并在构造时提供两个请求副本。

下面是请求的简单实现:

#include <atomic>
#include <future>
#include <memory>

template <class T>
class Request {
 public:
  struct Detail {
   std::atomic<bool> is_canceled_{false};
   std::promise<T> promise_;
   std::future<T> future_ = promise_.get_future();
  };

  static auto NewRequest() {
    std::unique_ptr<Request> copy1{new Request()};
    std::unique_ptr<Request> copy2{new Request(*copy1)};

    return std::make_pair(std::move(copy1), std::move(copy2));
  }

  Request(Request &&) = delete;

  ~Request() {
    detail_->is_canceled_.store(true);
  }

  Request &operator=(const Request &) = delete;
  Request &operator=(Request &&) = delete;

  // simple api
  std::promise<T> &Promise(const WorkerType &) {
    return detail_->promise_;
  }
  std::future<T> &Future(const BossType &) {
    return detail_->future_;
  }

  // return value:
  // true if available, false otherwise
  bool CheckAvailable() {
    return detail_->is_canceled_.load() == false;
  }

 private:
  Request() : detail_(new Detail{}) {}
  Request(const Request &) = default;

  std::shared_ptr<Detail> detail_;
};

template <class T>
auto SendMessage() {
  auto result = Request<T>::NewRequest();
  // TODO : send result.second(the another copy) to the worker
  return std::move(result.first);
}

新请求由工厂函数构造NewRequest,返回值为a std::pair,其中包含两个std::unique_ptr,每个都保存新创建的请求的副本。

worker 现在可以使用成员函数CheckAvailable()来检查请求是否被取消。

并且共享状态由 std::shared_ptr 正确管理(我相信)。

注意std::promise<T> &Promise(const WorkerType &): const 引用参数(应该根据你的实现替换为适当的类型)是为了防止老板意外调用这个函数,而工人应该能够轻松地提供一个适当的参数来调用这个函数。对于std::future<T> &Future(const BossType &).

于 2017-02-10T17:15:20.860 回答