对future,promise,async,packaged_task的彻底理解

1. future:

future的引入是为了解决thread并不提供直接接收返回值的机制的问题。

std::thread 的设计理念是:

只负责调度和执行线程函数,不负责管理其结果。

比如:

int do_work() {
    return 42;
}

int main() {
    std::thread t(do_work); // 编译通过,但返回值 42 被忽略了
    t.join();
}

所以,如果你想要线程函数返回值,你需要使用 std::future 配合 std::asyncstd::promise 来实现。

2. async

可以使用 std::async 启动一个异步任务。和std::thread不同, std::async 会返回一个 std::future 对象,这个对象持有最终计算出来的结果。当需要这个值时,只需要调用这个对象的get()成员函数;它阻塞线程直到期望值状态为就绪为止。

#include <future>
#include <iostream>

int do_work() {
    return 42;
}

int main() {
    std::future<int> result = std::async(std::launch::async, do_work);
    std::cout << "Result: " << result.get() << std::endl;
    return 0;
}

async传参的方式和thread一样:

#include <string>
#include <future>
struct X
{
    void foo(int,std::string const&);
    std::string bar(std::string const&);
};
X x;
auto f1=std::async(&X::foo,&x,42,"hello");
// 调用p->foo(42,"hello"),p是指向x的指针
auto f2=std::async(&X::bar,x,"goodbye");
// 调用tmpx.bar("goodbye"), tmpx是x的拷贝副本
struct Y
{
    double operator()(double);
};
Y y;
auto f3=std::async(Y(),3.141);
// 调用tmpy(3.141),tmpy通过Y的移动构造函数得到
auto f4=std::async(std::ref(y),2.718);
// 调用y(2.718)
X baz(X&);
std::async(baz,std::ref(x));
// 调用baz(x)
class move_only
{
public:
    move_only();
    move_only(move_only&&)
    move_only(move_only const&) = delete;
    move_only& operator=(move_only&&);
    move_only& operator=(move_only const&) = delete;
    void operator()();
};
auto f5=std::async(move_only());
// 调用tmp(),tmp是通过std::move(move_only())构造得到

async第一个参数可选:

This parameter is of the type std::launch,
and can either be std::launch::deferred to indicate that the function call is to be
deferred until either wait() or get() is called on the future, std::launch::async to
indicate that the function must be run on its own thread, or std::launch::deferred
| std::launch::async to indicate that the implementation may choose. This last
option is the default. If the function call is deferred, it may never run.

代码说明:

auto f6=std::async(std::launch::async,Y(),1.2);
// 在新线程上执行
auto f7=std::async(std::launch::deferred,baz,std::ref(x));
// 在wait()或get()调用时执行
auto f8=std::async(
std::launch::deferred | std::launch::async,
baz,std::ref(x));
// 实现选择执行方式
auto f9=std::async(baz,std::ref(x));
f7.wait();
//调用延迟函数

3. packaged_task

#include <deque>
#include <mutex>
#include <future>
#include <thread>
#include <utility>
std::mutex m;
std::deque<std::packaged_task<void()> > tasks;
bool gui_shutdown_message_received();
void get_and_process_gui_message();
void gui_thread()
{
  while(!gui_shutdown_message_received())
  {
    get_and_process_gui_message();
    std::packaged_task<void()> task;
    {
        std::lock_guard<std::mutex> lk(m);
        if(tasks.empty())
            continue;
        task=std::move(tasks.front());
        tasks.pop_front();
    }
    task();
  }
}
std::thread gui_bg_thread(gui_thread);
template<typename Func>
std::future<void> post_task_for_gui_thread(Func f)
{
    std::packaged_task<void()> task(f);
    std::future<void> res=task.get_future();
    std::lock_guard<std::mutex> lk(m);
    tasks.push_back(std::move(task));
    return res;
}

4. promise

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

void do_work(std::promise<int> p) {
    p.set_value(42);
}

int main() {
    std::promise<int> p;
    std::future<int> f = p.get_future();
    std::thread t(do_work, std::move(p));
    std::cout << "Result: " << f.get() << std::endl;
    t.join();
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值