白话《C++》第12章并发,Page539 异步绑定和任务包裹

复习一下函数绑定:

int action(string s, int i, int v1, int v2, int v3)
{
    cout << i << ":" << s << endl;
    return s.size() + v1 + v2 + v3;
}

只是需要一个好多入参的函数而已,接下来造一个函数,用于绑定action和它的第1,3,4,5个入参:

void bind_action_and_parameters(std::string const& message)
{
    int item_1, item_2, item_3;

    cout << "请输入三个整数:";
    cin >> item_1 >> item_2 >> item_3;

    //开始绑
    typedef std::function<int (string, int, int, int)> Action;
    Action f = std::bind(action, placeholders::_1, item_1, item_2, item_3);

    ///典型用法:把绑定好的结果传递出去
    foo(f);
}

不带“策略”入参的async()函数的入参列表是“(动作、入参1、入参2、入参3……)”,回头再看bind()函数的入参列表,二者是不是很像?二者都不立即执行动作,而是将动作和动作所需的数据打包;

主要区别在于,bind()在当前线程打包,并得到一个“包裹”对象,该对象可在当前线程或者交给其他线程执行;

async()则不关心绑定的细节,终点解决如何在当前线程得到其他线程执行某个“包裹”的结果,即“存根”。

如果async()调用时指定使用“拖延”策略,在效果上就更接近bind()了。

还有一个细节上的区别:由于bind()最终动作调用代码由我们自己写,因此在绑定时可以只绑定部分数据,其他数据用“placeholders::_1、placeholders::_2”等预定义的常量代替。

async()对操作的调用由标准库的作者实现,如果我们不给足数据,那边标准库要调用,它怎么补?

继续以“射击,枪,子弹,敌人”为例。bind()的情况是子弹上枪膛,枪挂在身上找敌人,找到后再瞄准射击;

async()的情况是子弹上枪膛,把枪交给一个小弟,交待他执行“找敌人,瞄准射击”的操作,而我们保留关注操作结果的权利和途径。

当然也可以在bind()之后,再通过async()交给另一个线程运行。当我们连到时是自己(当前线程)还是别人(其他线程)来执行这个动作都无法一下子做决定,可手上又已经有了部分该动作所需的数据时,就特别需要这两兄弟“强强联手”。

此处举一个“四强联手”的例子,多两个“强”是指lambda表达式和auto:

可以看到,若是同步执行,则在当前线程内执行,若是异步执行,则新开一个线程,在新的线程内执行。

不考虑例中选择“同步”执行的情况,将整件事简化为:在前面通过bind()绑定操作和数据,得到一个“包裹”对象,而后在需要时将该“包裹”传递给async()以实现异步调用。

对应的需求是:我想打包一个异步任务,但现在不执行,将来需要时再执行。

C++标准库使用一个很形象的名字packaged_task <T>,T是某种操作的类型。操作可以是函数、函数对象、lambda、bind()的结果或function <T>等。

int add(int i1, int i2) {return (i1 + i2);}

int main()
{
    packaged_task <int(int, int)> pkg(add);

    future <int> r = pkg.get_future(); 
    pkg(10, 11); 

    cout << r.get() << endl;
    return 0;
}

005行,创建一个“packaged_task(包裹任务)”。“包裹”中含有待执行的操作,本例为add()函数。“包裹”里没有包含操作所需要的入参,如果有需要,请结合bind()使用

007行,调用packaged_task <T>的get_future()方法,从“包裹”中得到一个“存根”。

008行,调用pkg()。其实pkg是一个对象变量,packaged_task<T>是类模板。重点是此处调用机制等同于不带“策略”版本的async()函数调用,同步异步皆可能。

010行,使用前面的“存根”对象查询、等待任务执行结果

有了bind(),邦德可以把枪和子弹装好,遇见敌人再开枪;加上packaged_task(),邦德就可以将子弹交给跟班,遇上紧急情况就让跟班开枪,那邦德忙什呢?《白话C++》后面章节,俄罗斯方块见

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值