C++ 11 promise future

1. 简单用例

future和promise的作用是在不同线程之间传递数据。

简单的例子:假设线程1需要线程2的数据,那么组合使用方式如下:

  • 线程1初始化一个promise对象和一个future对象, promise传递给线程2, 相当于线程2对线程1的一个承诺,future相当于一个接受一个承诺,用来获取未来线程2传递的值。
  • 如果值未返回,则一直会阻塞。
#include <iostream> // std::cout, std::endl
#include <thread>   // std::thread
#include <string>   // std::string
#include <future>   // std::promise, std::future
#include <chrono>   // seconds
using namespace std::chrono;

void read(std::future<std::string> *future) {
    // future会一直阻塞,直到有值到来
    std::cout << future->get() << std::endl;
}

int main() {
    // promise 相当于生产者
    std::promise<std::string> promise;
    // future 相当于消费者, 右值构造
    std::future<std::string> future = promise.get_future();
    // 另一线程中通过future来读取promise的值
    std::thread thread(read, &future);
    // 让read等一会儿:)
    std::this_thread::sleep_for(seconds(1));
    // 
    promise.set_value("hello future");
    // 等待线程执行完成
    thread.join();

    return 0;
}
// 控制台输: hello future

2. 并行例子1

在rpc调用接口,经常会遇到一种情况就是, 同时从多个rpc接口获取内容,然后将数据在主线程中进行合并。一般情况下,如果cpu耗时的任务启用线程来执行比较合适,而io耗时的任务一般采用协程来处理。这里使用promise和future解决这个问题。

#include<thread>
#include<future>
#include<iostream>      
                                                                         
using namespace std;
                    
// 子线程
void TaskOne(std::promise<std::string> *p) {
  p->set_value("one");
}
   
// 子线程
void TaskTwo(std::promise<std::string> *p) {
  p->set_value("two");
}

int main() {        
  std::promise<std::string> p1;
  std::promise<std::string> p2;                         
  std::future<std::string> f1 = p1.get_future();
  std::future<std::string> f2 = p2.get_future();
 
  std::thread t1 = std::thread(TaskOne, &p1);
  std::thread t2 = std::thread(TaskTwo, &p2);
  t1.join();
  t2.join();

  // 主线程把结果合并
  cout << f1.get() << endl;
  cout << f2.get() << endl;
}

g++ test.cpp -lpthread -std=c++11

2. 并行例子2

有时候需要传递结构体,而不仅仅一个数组。

#include<thread>
#include<future>
#include<iostream>
#include<string>

using namespace std;

struct Data {
  int number = 1;
  string str = "data";
};

// 子线程
void TaskOne(std::promise<Data> *p) {
  Data data;
  data.number = 2;
  p->set_value(data);
}
// 子线程
void TaskTwo(std::promise<std::string> *p) {
  p->set_value("two");
}

int main() {
  std::promise<Data> p1;
  std::promise<std::string> p2;
  std::future<Data> f1 = p1.get_future();
  std::future<std::string> f2 = p2.get_future();

  std::thread t1 = std::thread(TaskOne, &p1);
  std::thread t2 = std::thread(TaskTwo, &p2);
  t1.join();
  t2.join();

  // 主线程把结果合并
  auto data = f1.get();
  cout << data.number << endl;
  cout << data.str << endl;
  cout << f2.get() << endl;
}

g++ test.cpp -lpthread -std=c++11

3. 并行例子3

有时候还需要包装成类,在类中怎么实现呢?因为thread的执行函数只能是全局静态的,因此类的私有成员不可直接调用,这里使用bind方法实现静态函数的定义。具体如下:

#include<thread>
#include<future>
#include<iostream>
#include<string>

using namespace std;

class TestThread {
public:
struct Data {
  int number = 1;
  string str = "data";
};

void Run() {

  std::promise<Data> p1;
  std::promise<std::string> p2;
  std::future<Data> f1 = p1.get_future();
  std::future<std::string> f2 = p2.get_future();

  std::thread t1 = std::thread(std::bind(&TestThread::TaskOne, this, &p1));
  std::thread t2 = std::thread(std::bind(&TestThread::TaskTwo, this, &p2));
  t1.join();
  t2.join();

  // 主线程把结果合并
  auto data = f1.get();
  cout << data.number << endl;
  cout << data.str << endl;
  cout << f2.get() << endl;

}

// 子线程
void TaskOne(std::promise<Data> *p) {
  Data data;
  data.number = 2;
  p->set_value(data);
}

// 子线程
void TaskTwo(std::promise<std::string> *p) {
  p->set_value("two");
}

};

int main() {
  //TestThread* t = new TestThread();
  //t->Run();
  TestThread t;
  t.Run();
}

3. 并行例子4

rpc传输协议大部分以pb协议为主,通常需要传递的是一个pb的数据结构,这里提供使用pb的结构体,实现数据传输。

  • 安装pb
protobuf-cpp-3.8.0.zip
  • 设计pb文件
package mt;
syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}
  • 生成C++文件
/usr/local/bin/protoc -I=. --cpp_out=. test.proto 
  • 简单makefile设计
objects = test.pb.o test.o
main : $(objects)
        cc -o main $(objects) -L/usr/local/lib -lprotobuf -lpthread -lstdc++
test.o : test.cpp test.pb.h
        cc -c test.cpp
test.pb.o : test.pb.cc test.pb.h
        cc -c test.pb.cc
clean :
        rm main $(objects)
  • 代码实现
#include<thread>
#include<future>
#include<iostream>
#include<string>

#include "test.pb.h"

using namespace std;
using namespace mt;

class TestThread {
public:
void Run() {

  std::promise<SearchRequest> p1;
  std::promise<std::string> p2;
  std::future<SearchRequest> f1 = p1.get_future();
  std::future<std::string> f2 = p2.get_future();

  std::thread t1 = std::thread(std::bind(&TestThread::TaskOne, this, &p1));
  std::thread t2 = std::thread(std::bind(&TestThread::TaskTwo, this, &p2));
  t1.join();
  t2.join();

  // 主线程把结果合并
  auto data = f1.get();
  cout << data.query() << endl;
  cout << f2.get() << endl;

}

// 子线程
void TaskOne(std::promise<SearchRequest> *p) {
  SearchRequest data;
  data.set_query("test");
  p->set_value(data);
}

// 子线程
void TaskTwo(std::promise<std::string> *p) {
  p->set_value("two");
}

};

int main() {
  //TestThread* t = new TestThread();
  //t->Run();
  TestThread t;
  t.Run();
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值