栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++多线程--std::packaged

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++多线程--std::packaged

0 引言

本篇文章介绍 用于实现现代C++多线程中Task的另一个工具模版类:std::packaged_task.

关于C++多线程实现Task的工具模版类,前面已经介绍了std::promise 和 std::future, 具体可参考

C++多线程 task--std::promise和std::future_qls315的博客-CSDN博客

1 std::packaged_task介绍

std::packaged_task是一个模版类,其主要有如下几个功能

  • 将std::future同函数和可调用对象绑定
  • std::packaged_task对象是一个可调用对象
  • 通过调用std_packaged_task对象,会调用其封装的函数或者可调用对象,并将相应的结果存储在数据channel中,使与函数或可调用对象绑定的std::future变为ready
  • 可将其应用在线程池或者任务管理机制中

std::packaged_task的函数声明如下所示

template< class > class packaged_task; //not defined

template< class R, class ...ArgTypes >
class packaged_task;

由上述模版声明可知,std::packaged_task的模版参数为一个函数签名.

std::packaged_task是一个不可拷贝对象。

2 相应接口说明

其提供了如下几种接口

pack.swap(pack2)

std::swap(pack, pack2)   // 交换底层的task

pack.valid()          // 检查std::packaged_task是否拥有一个有效的函数

pack.get_future()     // 获得与其封装的函数相绑定的future

pack.make_ready_at_thread_exit(ex) // 执行相应的函数,其结果在线程退出时写到数据管道

pack.reset()      // 重置task的状态,并废弃以前执行的结果

此处为了进一步理解std::packaged_task, 给出《C++ Concurrency in Action》中关于std::packaged _task *,int)>的实现,其定义如下

template<>
class packaged_task*,int)> {
public:
    template
    explicit packaged_task(Callable&& f);
    std::future get_future();
    void make_ready_at_thread_exit(std::vector*,int);
    void reset();
    void swap( packaged_task& other ) noexcept;
    bool valid() const noexcept;
    void operator()(std::vector*,int);
};

进一步说明 std::packaged_task是一个可调用对象,其可以用在可调用对象使用的任何地方。

3 代码示例

本部分代码主要摘抄至std::packaged_task - cppreference.com

其具体代码实现如下

#include 
#include 
#include 
#include 
#include 
 
void task_lambda() {
  std::packaged_task task([](int a, int b) {
      return std::pow(a, b); 
  });
  std::future result = task.get_future();
 
  task(2, 9);
 
  std::cout << "task_lambda:t" << result.get() << 'n';
}
 
void task_thread() {
    std::packaged_task task([](int a, int b) {
      return std::pow(a, b); 
    });
    std::future result = task.get_future();
 
    std::thread task_td(std::move(task), 2, 10);
    task_td.join();
 
    std::cout << "task_thread:t" << result.get() << 'n';
}
 
int main() {
    task_lambda();
    task_thread();
    return 0;
}

上述代码示例,可自行验证输出。

本文最后给出一个使用std::packaged_task的reset接口的示例代码,其实现如下

#include 
#include 
#include 
#include 
#include
void calcProducts(std::packaged_task&task,
                  const std::vector>& pairs) {
  for (auto& pair: pairs){
    auto fut = task.get_future();
    task(pair.first, pair.second);
    std::cout << pair.first << " * " << pair.second << " = " << fut.get()
              << std::endl;
    task.reset();
  } 
}

int main(){

  std::vector> allPairs; 
  allPairs.push_back(std::make_pair(1, 2)); 
  allPairs.push_back(std::make_pair(2, 3));
  
  std::packaged_task task{[](int fir, int sec) { 
    return fir * sec; 
    }};
  
  calcProducts(task, allPairs);
  std::cout << std::endl;
  std::thread t(calcProducts, std::ref(task), allPairs); 
  t.join();
  std::cout << std::endl;
  return 0;
}

上述输出结果如下所示

 4 总结

本文讲解和总结了std::packaged_task的相关概念以及相应的使用,后续文章将进一步讲解C++多线程task中的std::async模版类。

若有机会,后续会讲解这些类如何构建线程池。

std::packaged_task - cppreference.com

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1008445.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号