16.5.6  模板类packaged_task

16.5.6 模板类 packaged_ task

模板类packaged_task定义了包裹一个函数或可调用对象的一种类型,这使得函数或可调用对象的返回值被存储在future类型对象中。当packaged_task类型对象被激活之后,其存储任务会被激活,并且其结果或会被存储至共享状态中。共享该共享状态的任意future类型对象均可以访问该存储值。

该类的声明形式为:

978-7-111-51399-5-Chapter16-105.jpg

除了各种形式的构造函数之外,该类主要包含可用于返回future类型对象的get_future(),swap()函数和valid(),make_ready_at_thread_exit()函数和reset()以及一个有效的赋值符号。

而构造函数具有多种形式:

978-7-111-51399-5-Chapter16-106.jpg

各函数的具体使用形式:

第一种构函数用于构造一个默认空对象。该对象被初始化,但是不包含共享状态,不包含存储任务。

第二种构造函数template<class F>explicit packaged_task(F&& f)用于初始化一个共享状态,并且被包装任务由参数f指定。

第三种构造函数是带自定义内存分配器的构造函数,与默认构造函数类似,但是使用自定义分配器来分配共享状态。

第六种构造函数用于获取rhs的共享状态,并将rhs中的存储对象移动至新构造的对象中,使rhs变为不再拥有共享状态。

get_future()函数:该函数用于返回该对象相关共享状态的future类型对象。

valid()函数:该函数用于判断当前packaged_task对象是否和共享状态相关联。

make_ready_at_thread_exit()函数:该函数会调用被包装的任务,并向任务传递参数,类似于std::packaged_task的operator()成员函数。但是与operator()函数不同的是,make_ready_at_thread_exit并不会立即设置共享状态的标志为“ready”,而是在线程退出时设置共享状态的标志。若与该packaged_task共享状态相关联的future对象在future::get()处等待,则当前的future::get()调用会被阻塞,直到线程退出。而一旦线程退出,future::get()调用继续执行,或者抛出异常。函数的参数就是对象的任务的参数。关于make_ready_at_thread_exit()函数的使用,本书作者是使用Visual Studio 2012版本的V C++开发环境。该开发环境提供的threadcall.cpp文件中包含如下代码:

978-7-111-51399-5-Chapter16-107.jpg

978-7-111-51399-5-Chapter16-108.jpg

在启动线程时,如果发生异常,在异常处理模块(catch块)中,上述代码明显有错误:

978-7-111-51399-5-Chapter16-109.jpg

由于作者使用的是VC++ 2012版本,大于1300,符合#if的条件,程序直接调用termi-nate(),之后调用abort(),程序会弹出异常对话框,终止运行。

该函数可能导致异常的情况如下:

异常类型 错误条件 描述

future_error future_errc::no_state 该对象没有共享状态

future_error future_errc::promise_already_satisfied 被存储的任务已经被调用

reset()函数:该函数用于重置packaged_task的共享状态,但是保留之前被包装的任务。

swap()函数:该函数用于交换packaged_task的共享状态。

operator()函数:该函数用于调用该packaged_task对象所包装的对象。调用该函数一般会发生以下两种情况:

1)若成功调用packaged_task所包装的对象,则返回值(如果被包装的对象有返回值的话)被保存在packaged_task的共享状态中。

2)若调用packaged_task所包装的对象失败,并且抛出了异常,则异常也会被保存在packaged_task的共享状态中。

以上两种情况都使共享状态的标志变为ready,因此其他等待该共享状态的线程可以获取共享状态的值或者异常并继续执行下去。

该模板类的具体使用方法参见例16-23。例16-24用于讲述算法swap()在packaged_task类型对象交换信息中的应用。

例16-23

978-7-111-51399-5-Chapter16-110.jpg

978-7-111-51399-5-Chapter16-111.jpg

例16-23的执行效果如图16-24所示。

978-7-111-51399-5-Chapter16-112.jpg

图16-24 例16-23的执行效果

例16-24

978-7-111-51399-5-Chapter16-113.jpg

978-7-111-51399-5-Chapter16-114.jpg

例16-24的执行效果如图16-25所示。

978-7-111-51399-5-Chapter16-115.jpg

图16-25 例16-24的执行效果