• C++11获取线程的返回值


    C++11 std::future and std::promise

    在许多时候,我们会有这样的需求——即我们想要得到线程返回的值。
    但是在C++11 多线程中我们注意到,std::thread对象会忽略顶层函数的返回值。
    那问题来了,我们要怎么获得线程的返回值呢?

    我们通过一个例子来说明如何实现这个需求。

    假设我们的app会创建一个线程来压缩一个文件夹,该线程在压缩完文件夹后会返回压缩文件 *.zip 和这个zip文件的大小,我们现在就想获得这个线程的返回值。

    有两种方法可以实现这个需求:

    1. 传统的方法:在线程间共享指针

    传递一个指针给压缩文件的线程,表示压缩文件的线程将会把值写入指针指向的内存空间。此时主线程将用条件变量等待值被写入,当压缩文件线程把值写入指针指定的内存后,将唤醒(signal)条件变量,然后主线程将被唤醒,然后从指针指向的内存中获取返回值。

    为了实现获取一个返回值的需求,使用传统的方法,我们需要条件变量(condition variable), 互斥量(mutex),和指针三个对象。
    如果假设,我们需要获得压缩线程里三个返回值,情况会变得更加复杂。

    std::future就是来简化这个编程过程的

    2. C++11的方法:使用std::futurestd::promise

    人如其名,std::futurestd::promise对象就和他们的名字一样。这两个类在获取程序返回值的时候需要配合使用

    std::future,是一个类模板,它存储着一个未来的值。
    那问题来了,未来的值是什么鬼?

    实际上一个std::future对象里存储着一个在未来会被赋值的变量,这个变量可以通过std::future提供的成员函数std::future::get()来得到。如果在这个变量被赋值之前就有别的线程试图通过std::future::get()获取这个变量,那么这个线程将会被阻塞到这个变量可以获取为止。

    std::promise同样也是一个类模板,它的对象承诺会在未来设置变量(这个变量也就是std::future中的变量)。每一个std::promise对象都有一个与之关联的std::future对象。当std::promise设置值的时候,这个值就会赋给std::future中的对象了。


    我们一步一步来看一下如何做

    1. 在主线程中创建std::promise对象
    std::promise<int> promiseObj;
    

    上面定义的promise对象还没有任何关联的值。但是它承诺某个线程将会设置与其关联的值,并且,当值被设置以后,可以通过与promise关联的std::future对象来获取该值。

    假设我们的主线程将创建的std::promise对象传递给了压缩线程,那主线程要怎么知道压缩线程已经设置好了值呢?
    答案就是使用 std::future对象

    // main thread
    std::future<int> futureObj = promiseObj.get_future();
    int val = futureObj.get();
    
    // compression thread
    promiseObj.set_value(45);
    

    compression thread未执行set_value()时,如果主线程调用了futureObj.get(),那么主线程将会被阻塞。

    看整个时序图:
    Diagram

    最终代码

    #include<iostream>    //std::cout std::endl
    #include<thread>      //std::thread
    #include<future>      //std::future std::promise
    #include<utility>     //std::ref
    #include<chrono>      //std::chrono::seconds
    
    void initiazer(std::promise<int> &promiseObj){
        std::cout << "Inside thread: " << std::this_thread::get_id() << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
        promiseObj.set_value(35);
    }
    
    int main(){
        std::promise<int> promiseObj;
        std::future<int> futureObj = promiseObj.get_future();
        std::thread th(initiazer, std::ref(promiseObj));
        
        std::cout << futureObj.get() << std::endl;
    
        th.join();
        return 0;
    }
    

    本文参考于C++11 Multithreading – Part 8: std::future , std::promise and Returning values from Thread,并做了适当修改

  • 相关阅读:
    进制转换问题
    奶牛野炊
    BFS
    深搜DFS
    Map容器之热血格斗场
    衣服尺码
    BZOJ2789 [Poi2012]Letters
    BZOJ1098 [POI2007]办公楼biu
    BZOJ1753 [Usaco2005 qua]Who's in the Middle
    BZOJ2442 [Usaco2011 Open]修剪草坪
  • 原文地址:https://www.cnblogs.com/pluviophile/p/cpp11-future.html
Copyright © 2020-2023  润新知