1、std::packaged_task介绍
类模板 std::packaged_task 包装任何可调用 (Callable) 目标(函数、 lambda 表达式、 bind 表达式或其他函数对象),使得能异步调用它。其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中。—摘抄自https://www.apiref.com/cpp-zh/cpp/thread/packaged_task.html
接下来看下std::packaged_task的定义:
/// packaged_task
template<typename _Res, typename... _ArgTypes>
class packaged_task<_Res(_ArgTypes...)>
{
typedef __future_base::_Task_state_base<_Res(_ArgTypes...)> _State_type;
shared_ptr<_State_type> _M_state;
public:
// Construction and destruction
packaged_task() noexcept { }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2095. missing constructors needed for uses-allocator construction
template<typename _Allocator>
packaged_task(allocator_arg_t, const _Allocator& __a) noexcept
{ }
template<typename _Fn, typename = typename
__constrain_pkgdtask<packaged_task, _Fn>::__type>
explicit
packaged_task(_Fn&& __fn)
: packaged_task(allocator_arg, std::allocator<int>(),
std::forward<_Fn>(__fn))
{ }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2097. packaged_task constructors should be constrained
template<typename _Fn, typename _Alloc, typename = typename
__constrain_pkgdtask<packaged_task, _Fn>::__type>
explicit
packaged_task(allocator_arg_t, const _Alloc& __a, _Fn&& __fn)
: _M_state(__create_task_state<_Res(_ArgTypes...)>(
std::forward<_Fn>(__fn), __a))
{ }
~packaged_task()
{
if (static_cast<bool>(_M_state) && !_M_state.unique())
_M_state->_M_break_promise(std::move(_M_state->_M_result));
}
// No copy
packaged_task(const packaged_task&) = delete;
packaged_task& operator=(const packaged_task&) = delete;
template<typename _Allocator>
packaged_task(allocator_arg_t, const _Allocator&,
const packaged_task&) = delete;
// Move support
packaged_task(packaged_task&& __other) noexcept
{ this->swap(__other); }
template<typename _Allocator>
packaged_task(allocator_arg_t, const _Allocator&,
packaged_task&& __other) noexcept
{ this->swap(__other); }
packaged_task& operator=(packaged_task&& __other) noexcept
{
packaged_task(std::move(__other)).swap(*this);
return *this;
}
void
swap(packaged_task& __other) noexcept
{ _M_state.swap(__other._M_state); }
bool
valid() const noexcept
{ return static_cast<bool>(_M_state); }
// Result retrieval
future<_Res>
get_future()
{ return future<_Res>(_M_state); }
// Execution
void
operator()(_ArgTypes... __args)
{
__future_base::_State_base::_S_check(_M_state);
_M_state->_M_run(std::forward<_ArgTypes>(__args)...);
}
void
make_ready_at_thread_exit(_ArgTypes... __args)
{
__future_base::_State_base::_S_check(_M_state);
_M_state->_M_run_delayed(std::forward<_ArgTypes>(__args)..., _M_state);
}
void
reset()
{
__future_base::_State_base::_S_check(_M_state);
packaged_task __tmp;
__tmp._M_state = _M_state;
_M_state = _M_state->_M_reset();
}
};
2、std::packaged_task重要的函数介绍
void swap(packaged_task& __other);//两个packaged task互换
bool valid();//如果有一个新的shared state就产生true。
// Result retrieval
future<_Res> get_future();//获得一个future 对象,可以用来取的shared state
// Execution
void operator()(_ArgTypes... __args);
void make_ready_at_thread_exit(_ArgTypes... __args);
//调用task并且在线成退出时使shared state为ready
void reset(); //建立一个新的shared state,会使shared state为ready
/// swap
template<typename _Res, typename... _ArgTypes>
swap(packaged_task<_Res(_ArgTypes...)>& __x, packaged_task<_Res(_ArgTypes...)>& __y);
3、std::packaged_task用法示例
具体示例代码如下:
/*************************************************************************
> File Name: thread_packaged_task.cpp
> Author: 小和尚敲木鱼
> Mail:
> Created Time: Tue 21 Sep 2021 02:40:24 AM PDT
************************************************************************/
#include <iostream>
#include <thread>
#include <string>
#include <vector>
#include <list>
#include <mutex>
#include <future>
#include <chrono>
using namespace std;
/*****************************文件说明***********************************/
int function_1(int param)//线程
{
int ret = 10;
std::cout << __func__ << "param =" << param << std::endl;
std::cout << "handle thread id ="<< std::this_thread::get_id() << std::endl;
std::chrono::milliseconds sleep_time(500);
std::this_thread::sleep_for(sleep_time);
std::cout << __func__ << " thread id ="<< std::this_thread::get_id() << std::endl;
std::cout << __func__ << " return = "<< ret + param << std::endl;
return (ret + param);
}
int main(int agc,char * agv[])
{
int temp = 20;
std::cout << "Main thread id =" << std::this_thread::get_id() << std::endl;
std::packaged_task<int(int)> handle_task(function_1);//创建packaged_task
std::thread thread_test(std::ref(handle_task),temp);
std::future<int> result = handle_task.get_future();
std::cout << "###################" << std::endl;
std::cout << "result = " << result.get() << std::endl;
if (thread_test.joinable())
thread_test.join();
return 0;
}
//OUT
//Main thread id =140609886185280
//###################
//function_1param =20
//handle thread id =140609868805888
//function_1 thread id =140609868805888
//function_1 return = 30
//result = 30
/**************************end of file**********************************/
4、总结
std::packaged_task简单来说就是,打包一个异步任务去完成,完成打包后就不用管了,到合适的地点去获取相应的执行结果就可以了。非常的银杏。
Todo:
后续补充其他细节。