packaged_task<> Example and Tutorial

packaged_task<> Example and Tutorial

本文将主要讨论std::packagded_task的特性和使用

std::packaged_task<>

std::packaged_task<>是一个代表异步任务的类模版,它包括两部分:

  • 一个可调用的实体。例如函数、lambda函数或者函数对象;
  • 一个存储着返回值的共享状态或者由相关回调抛出的异常;

Need of std::packaged_task<>

假设我们想利用以下的函数从DB中获取数据:

1
2
3
4
5
6
std::string getDataFromDB( std::string token)
{
// Do some stuff to fetch the data
std::string data = "Data fetched from DB by Filter :: " + token;
return data;
}

一种方法是使用前面提及的,在函数中传递std::promise<>对象。

另一种方法就是使用std::packaged_task<>

Using packaged_task<> with function to create Asynchronous tasks

当std::packaged_task<>在独立的线程上调用时,它会调用相关的回调并把返回值存储到内部的共享状态里。这些值可以在其它线程或者main函数里通过future对象访问。

以上面的函数为例,我们可以创建一个packaged_task对象。

1
std::packaged_task<std::string (std::string)> task(getDataFromDB);

然后在将std::packaged_task传递进线程之前,先从中获取future对象。由于std::packaged_task是不可以拷贝的,因此需要用move。

1
2
std::future<std::string> result = task.get_future();
std::thread th(std::move(task), "Arg");

当此函数返回值时,std :: packaged_task<>将其设置为关联的共享状态,getDataFromDB()返回的结果或异常最终会在相关的future对象中可用。

main函数阻塞调用:

1
std::string data =  result.get();