C++中Future和Promise的一种简单实现

女主宣言

由于工作需求,笔者最近在阅读 Pulsar C++ 客户端的实现,发现该客户端虽然是基于 C++11 编写的,但却自己编写了 Future 和 Promise 类,随着阅读的深入,也体会到了在这里”重复造轮子“的原因。本文将根据lib/Future.h中的源码,讲述C++中Future和Promise的一种简单实现~

PS:丰富的一线技术、多元化的表现形式,尽在“360云计算”,点关注哦!

1

前言

众所周知,C++11 提供了对并发编程的支持。首先提供了对不同平台的线程设施的简单包装 thread,并提供了 native_handle() 方法可以得到平台相关的线程句柄,从而调用底层线程相关的函数。另外,C++11 还提供了 future 和 promise 来支持基于任务的程序设计。

1

C++11的并发API

首先回顾下 C++11 的并发设施。

std::thread

如果熟悉 pthread 库的话,那么 C++11 的 std::thread 会非常容易上手,它使用了可变模板参数这一技术,使得编写线程函数不必麻烦地进行 void* 和 T* 的相互转换。

举个例子,要在线程中将两个 int 求和然后转换成十六进制字符串,得到结果。

使用 pthread 的代码:

#include <pthread.h>


#include <iostream>
#include <string>
using namespace std;


struct Package {
  int x, y;            // input
  std::string result;  // output


  void calculate() { result = std::to_string(x + y); }
};


int main(int argc, char* argv[]) {
  pthread_t tid;
  Package package{1, 3, ""};
  pthread_create(
      &tid, nullptr,
      [](void* param) -> void* {  // 线程函数必须是 void* (void*)
        static_cast<Package*>(param)->calculate();
        return nullptr;
      },
      &package);  // 传入 void* 作为输入参数
  pthread_join(tid, nullptr);  // 第二个参数是 void**,如果非空的话可以得到线程函数返回的 void*
  cout << "result: " << package.result << endl;
  return 0;
}

为了简化代码,这里忽略 pthread API 的返回值检查,以及 param 是否为空的检查。可见,pthread 需要对参数打包成一个结构体。

再看看 std::thread 的等价实现:

#include <string>
#include <thread>
using namespace std;


int main(int argc, char* argv[]) {
  string result;
  thread t([](int x, int y,
              string& s) { s = to_string(x + y); },  // 函数签名是 T (Args...)
           1, 3, ref(result));
  t.join();
  cout << "result: " << result << endl;
  return 0;
}

最大的改进是线程函数签名从底层的 void*(void*) 变成了返回任意类型、接收任意数量和类型的参数的 T(Args&&...)。注意传入引用时需要用 std::ref 将引用转换成可拷贝的某种结构。

如何得到返回值

问题来了,其实上面的实现并不直观,毕竟将计算结果作为返回值,比将计算结果的引用作为输入参数要更符合直观。

std::thread 直接就无法得到返回值。反而 pthread 线程函数可以返回的那个 void* 保存返回结果,比如:

#include <pthread.h>


#include <iostream>
#include <string>
using namespace std;


struct Input {
  int x, y;


  std::string sum() const { return to_string(x + y); }
};


int main(int argc, char* argv[]) {
  Input input{1, 3};
  pthread_t tid;
  pthread_create(
      &tid, nullptr,
      [](void* param) -> void* {
        return new std::string(static_cast
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值