c++ 11 多线程支持 (std::packaged_task)

定义于头文件 
template< class > class packaged_task; // 不定义  (1) (C++11 起) 

template< class R, class ...Args >
class packaged_task;                  (2) (C++11 起) 

类模板 std::packaged_task 包装任何可调用 (Callable) 目标(函数、 lambda 表达式、 bind 表达式或其他函数对象),使得能异步调用它。其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中。

正如 std::function , std::packaged_task 是多态、具分配器的容器:可在堆上或以提供的分配器分配存储的可调用对象。

构造函数

std::packaged_task::packaged_task
packaged_task() noexcept;   (1) (C++11 起) 

template 
explicit packaged_task( F&& f ); (2) (C++11 起) 

template 
explicit packaged_task( std::allocator_arg_t, const Allocator& a, F&& f );
(3) (C++11 起)  (C++17 前) 

packaged_task( const packaged_task& ) = delete; (4) (C++11 起) 

packaged_task( packaged_task&& rhs ) noexcept;  (5) (C++11 起) 

构造新的 std::packaged_task 对象。

1) 构造无任务且无共享状态的 std::packaged_task 对象。

2) 构造拥有共享状态和任务副本的 std::packaged_task 对象,以 std::forward(f) 初始化副本。若 std::decay::type 与 std::packaged_task 是同一类型,则此构造函数不参与重载决议。

3) 构造拥有共享状态和任务副本的 std::packaged_task 对象,以 std::forward(f) 初始化副本。用提供的分配器分配存储任务所需的内存。 若 std::decay::type 与 std::packaged_task 是同一类型,则此构造函数不参与重载决议。

4) 复制构造函数被删除, std::packaged_task 仅可移动。

5) 以 rhs 之前所占有的共享状态和任务构造 std::packaged_task ,令 rhs 留在无共享状态且拥有被移动后的任务的状态。

参数

f - 要执行的可调用目标(函数、成员函数、 lambda 表达式、函数对象)
a - 存储任务时所用的分配器
rhs - 要移动的 std::packaged_task

异常

2) f 的复制/移动构造函数所抛的任何异常,而若内存分配失败则可能为 std::bad_alloc 。

3) f 的复制/移动构造函数,而若内存分配失败则有分配器的 allocate 函数所抛的任何异常。

4) (无)

析构函数

std::packaged_task::~packaged_task
~packaged_task();

抛弃共享状态并销毁存储的任务对象。

同 std::promise::~promise ,若在令共享状态就绪前抛弃它,则存储以 std::future_errc::broken_promise 为 error_code 的 std::future_error 异常。

参数

(无)

移动任务对象

std::packaged_task::operator=
packaged_task& operator=( const packaged_task& ) = delete; (1) (C++11 起) 

packaged_task& operator=( packaged_task&& rhs ) noexcept;  (2) (C++11 起) 

1) 复制赋值运算符被删除, std::packaged_task 仅可移动。

2) 若存在则释放共享状态,销毁先前保有的任务,并将 rhs 所占有的共享状态和任务移动到 *this 。令 rhs 无共享状态,并拥有被移动后的任务。

参数

rhs - 移动来源的 std::packaged_task

检查任务对象是否拥有合法函数

std::packaged_task::valid
bool valid() const noexcept;  (C++11 起) 

检查 *this 是否拥有共享状态。

参数

(无)

返回值

若 *this 拥有共享状态则为 true ,否则为 false 。

交换二个任务对象

std::packaged_task::swap
void swap( packaged_task& other ) noexcept;   (C++11 起) 

交换 *this 与 other 的共享状态和存储的任务。

参数

other - 要交换状态的 packaged_task

返回值

(无)

返回与承诺的结果关联的 std::future

std::packaged_task::get_future
std::future get_future();    (C++11 起) 

返回与 *this 共享同一共享状态的 future

get_future 只能对每个 packaged_task 调用一次。

参数

(无)

返回值

与 *this 共享同一共享状态的 future

异常

遇到下列条件时为 std::future_error 。

  • 已通过调用 get_future 取得共享状态。设置 error_category 为 future_already_retrieved 。
  • *this 无共享状态。设置 error_category 为 no_state 。


执行函数

std::packaged_task::operator()
void operator()( ArgTypes... args );   (C++11 起) 

args 为参数调用存储的任务。任务返回值或任何抛出的异常被存储于共享状态。令共享状态就绪,并解除阻塞任何等待此操作的线程。

参数

args - 调用时传递给存储任务的参数

返回值

(无)

异常

遇到下列条件时为 std::future_error :

  • 已调用存储的任务。设置 error_category 为 promise_already_satisfied 。
  • *this 无共享状态。设置 error_category 为 no_state 。

注意

operator() 的成功调用同步于对任何与 *this 共享其共享状态的 std::future 或 std::shared_future 的任何成员函数调用。

(C++14 前)

在共享状态已提供的同步保证外,无另外的同步保证。

(C++14 起)

 

重置状态,抛弃任何先前执行的存储结果

 std::packaged_task::reset
void reset();              (C++11 起) 

重置状态,抛弃先前执行的结果。构造共享状态。

等价于 *this = packaged_task(std::move(f)) ,其中 f 是存储的任务。

参数

(无)

返回值

(无)

异常

  • 若 *this 无共享状态则为 std::future_error 。设置 error_condition 为 no_state 。
  • 若无足够内存以分配新的共享状态则为 std::bad_alloc 。
  • packaged_task 的移动构造函数所抛的任何异常

执行函数,并确保结果仅在一旦当前线程退出时就绪

std::packaged_task::make_ready_at_thread_exit
void make_ready_at_thread_exit( ArgTypes... args );   (C++11 起) 

void make_ready_at_thread_exit( ArgTypes... args );

(C++11 起)

以转发的 args 为参数调用存储的任务。任务返回值或任何抛出的异常被存储于 *this 的共享状态。

仅在当前线程退出,并销毁所有线程局域存储期对象后,才令共享状态就绪。

参数

args - 调用时传递给存储任务的参数

返回值

(无)

异常

遇到下列条件时为 std::future_error :

  • 已调用存储的任务。设置 error_category 为 promise_already_satisfied 。
  • *this 无共享状态。设置 error_category 为 no_state 。

调用示例

#include 
#include 
#include 
#include 
#include 
#include 

void worker(std::future& output)
{
    std::packaged_task my_task{ [](bool & done)
    {
        done = true;
    } };

    auto result = my_task.get_future();

    bool done = false;

    my_task.make_ready_at_thread_exit(done); // 立即执行任务

    std::cout << "worker: done = " << std::boolalpha << done << std::endl;

    auto status = result.wait_for(std::chrono::seconds(0));
    if (status == std::future_status::timeout)
    {
        std::cout << "worker: result is not ready yet" << std::endl;
    }

    output = std::move(result);
}


int main()
{
    std::future result;

    std::thread{worker, std::ref(result)}.join();

    auto status = result.wait_for(std::chrono::seconds(0));
    if (status == std::future_status::ready)
    {
        std::cout << "main: result is ready" << std::endl;
    }
}

输出

c++ 11 多线程支持 (std::packaged_task)_第1张图片

特化 std::swap 算法

std::swap(std::packaged_task)
template< class Function, class... Args >
void swap( packaged_task &lhs,
           packaged_task &rhs ) noexcept;  (C++11 起) 

           packaged_task &rhs ) noexcept;

(C++11 起)

为 std::packaged_task 特化 std::swap 算法。交换 lhsrhs 的状态。等效地调用 lhs.swap(rhs) 。

参数

lhs, rhs - 要交换状态的 packaged_task

返回值

(无)

调用示例

#include 
#include 
#include 
#include 
#include 

// 避免对 std::pow 重载集消歧义的独有函数
int f(int x, int y)
{
    return std::pow(x, y);
}

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_bind()
{
    std::packaged_task task(std::bind(f, 2, 11));
    std::future result = task.get_future();

    task();

    std::cout << "task_bind:\t" << result.get() << '\n';
}

void task_thread()
{
    std::packaged_task task(f);
    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_bind();
    task_thread();
}

输出

c++ 11 多线程支持 (std::packaged_task)_第2张图片

 

你可能感兴趣的:(#,线程支持库,c++,多线程,packaged_task)