求凌天神帝txt下载笔云盘资源,作者君天帝

c/c++知识(92)
前面两讲《》,《》分别介绍了 std::thread 和 std::mutex,相信读者对 C++11 中的多线程编程有了一个最基本的认识,本文将介绍 C++11 标准中 &future& 头文件里面的类和相关函数。
&future& 头文件中包含了以下几个类和函数:
Providers 类:std::promise, std::package_taskFutures 类:std::future, shared_future.Providers 函数:std::async()其他类型:std::future_error, std::future_errc, std::future_status, std::launch.
std::promise 类介绍
promise 对象可以保存某一类型 T 的值,该值可被 future 对象读取(可能在另外一个线程中),因此 promise 也提供了一种线程同步的手段。在 promise 对象构造时可以和一个共享状态(通常是std::future)相关联,并可以在相关联的共享状态(std::future)上保存一个类型为 T 的值。
可以通过 get_future 来获取与该 promise 对象相关联的 future 对象,调用该函数之后,两个对象共享相同的共享状态(shared state)
promise 对象是异步 Provider,它可以在某一时刻设置共享状态的值。future 对象可以异步返回共享状态的值,或者在必要的情况下阻塞调用者并等待共享状态标志变为 ready,然后才能获取共享状态的值。
下面以一个简单的例子来说明上述关系
#include &iostream&
// std::cout
#include &functional&
// std::ref
#include &thread&
// std::thread
#include &future&
// std::promise, std::future
void print_int(std::future&int&& fut) {
int x = fut.get(); // 获取共享状态的值.
std::cout && &value: & && x && '\n'; // 打印 value: 10.
int main ()
std::promise&int& // 生成一个 std::promise&int& 对象.
std::future&int& fut = prom.get_future(); // 和 future 关联.
std::thread t(print_int, std::ref(fut)); // 将 future 交给另外一个线程t.
prom.set_value(<span style="color:#); // 设置共享状态的&#20540;, 此处和线程t保持同步.
return <span style="color:#;
std::promise 构造函数
default (1)
promise();
with allocator (2)
template &class Alloc& promise (allocator_arg_t aa, const Alloc& alloc);
copy [deleted] (3)
promise (const promise&) =
promise (promise&& x)
默认构造函数,初始化一个空的共享状态。带自定义内存分配器的构造函数,与默认构造函数类&#20284;,但是使用自定义分配器来分配共享状态。拷贝构造函数,被禁用。移动构造函数。
另外,std::promise 的 operator= 没有拷贝语义,即 std::promise 普通的赋&#20540;操作被禁用,operator= 只有 move 语义,所以 std::promise 对象是禁止拷贝的。
#include &iostream&
// std::cout
#include &thread&
// std::thread
#include &future&
// std::promise, std::future
std::promise&int&
void print_global_promise () {
std::future&int& fut = prom.get_future();
int x = fut.get();
std::cout && &value: & && x && '\n';
int main ()
std::thread th1(print_global_promise);
prom.set_value(<span style="color:#);
th1.join();
prom = std::promise&int&();
// prom 被move赋&#20540;为一个新的 promise 对象.
std::thread th2 (print_global_promise);
prom.set_value (<span style="color:#);
th2.join();
return <span style="color:#;
&std::promise::get_future 介绍
该函数返回一个与 promise 共享状态相关联的 future 。返回的 future 对象可以访问由 promise 对象设置在共享状态上的&#20540;或者某个异常对象。只能从 promise 共享状态获取一个 future 对象。在调用该函数之后,promise 对象通常会在某个时间点准备好(设置一个&#20540;或者一个异常对象),如果不设置&#20540;或者异常,promise 对象在析构时会自动地设置一个 future_error 异常(broken_promise)来设置其自身的准备状态。上面的例子中已经提到了
get_future,此处不再重复。
std::promise::set_value 介绍
generic template (1)
void set_value (const T& val);
void set_value (T&& val);
specializations (2)
void promise&R&&::set_value (R& val);
// when T is a reference type (R&)
void promise&void&::set_value (void);
// when T is void
设置共享状态的&#20540;,此后 promise 的共享状态标志变为 ready.
&std::promise::set_exception 介绍
为 promise 设置异常,此后 promise 的共享状态变标志变为 ready,例子如下,线程1从终端接收一个整数,线程2将该整数打印出来,如果线程1接收一个非整数,则为 promise 设置一个异常(failbit) ,线程2 在std::future::get 是抛出该异常。
#include &iostream&
// std::cin, std::cout, std::ios
#include &functional&
// std::ref
#include &thread&
// std::thread
#include &future&
// std::promise, std::future
#include &exception&
// std::exception, std::current_exception
void get_int(std::promise&int&& prom) {
std::cout && &Please, enter an integer value: &;
std::cin.exceptions (std::ios::failbit);
// throw on failbit
std::cin &&
// sets failbit if input is not int
prom.set_value(x);
} catch (std::exception&) {
prom.set_exception(std::current_exception());
void print_int(std::future&int&& fut) {
int x = fut.get();
std::cout && &value: & && x && '\n';
} catch (std::exception& e) {
std::cout && &[exception caught: & && e.what() && &]\n&;
int main ()
std::promise&int&
std::future&int& fut = prom.get_future();
std::thread th1(get_int, std::ref(prom));
std::thread th2(print_int, std::ref(fut));
th1.join();
th2.join();
return <span style="color:#;
std::promise::set_value_at_thread_exit 介绍
设置共享状态的&#20540;,但是不将共享状态的标志设置为 ready,当线程退出时该 promise 对象会自动设置为 ready。如果某个 std::future 对象与该 promise 对象的共享状态相关联,并且该 future 正在调用 get,则调用 get 的线程会被阻塞,当线程退出时,调用 future::get 的线程解除阻塞,同时 get 返回 set_value_at_thread_exit 所设置的&#20540;。注意,该函数已经设置了 promise 共享状态的&#20540;,如果在线程结束之前有其他设置或者修改共享状态的&#20540;的操作,则会抛出
future_error( promise_already_satisfied )。
std::promise::swap 介绍
交换 promise 的共享状态。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:42090次
积分:1026
积分:1026
排名:千里之外
原创:10篇
转载:306篇
(15)(1)(16)(5)(16)(18)(63)(5)(4)(23)(72)(17)(18)(7)(5)(4)(11)(16)(6)Posts - 110,
Articles - 2,
Comments - 188
10:55 by Haippy, ... 阅读,
上一讲《》主要介绍了 &future& 头文件中的 std::packaged_task 类,本文主要介绍 std::future,std::shared_future 以及 std::future_error,另外还会介绍 &future& 头文件中的 std::async,std::future_category 函数以及相关枚举类型。
std::future 介绍
前面已经多次提到过 std::future,那么 std::future 究竟是什么呢?简单地说,std::future 可以用来获取异步任务的结果,因此可以把它当成一种简单的线程间同步的手段。std::future 通常由某个 Provider 创建,你可以把 Provider 想象成一个异步任务的提供者,Provider 在某个线程中设置共享状态的值,与该共享状态相关联的 std::future 对象调用 get(通常在另外一个线程中) 获取该值,如果共享状态的标志不为 ready,则调用 std::future::get 会阻塞当前的调用者,直到 Provider 设置了共享状态的值(此时共享状态的标志变为 ready),std::future::get 返回异步任务的值或异常(如果发生了异常)。
一个有效(valid)的 std::future 对象通常由以下三种 Provider 创建,并和某个共享状态相关联。Provider 可以是函数或者类,其实我们前面都已经提到了,他们分别是:
std::async 函数,本文后面会介绍 std::async() 函数。
std::promise::get_future,get_future 为 promise 类的成员函数,详见 。
std::packaged_task::get_future,此时 get_future为 packaged_task 的成员函数,详见。
一个 std::future 对象只有在有效(valid)的情况下才有用(useful),由 std::future 默认构造函数创建的 future 对象不是有效的(除非当前非有效的 future 对象被 move 赋值另一个有效的 future 对象)。
&在一个有效的 future 对象上调用 get 会阻塞当前的调用者,直到 Provider 设置了共享状态的值或异常(此时共享状态的标志变为 ready),std::future::get 将返回异步任务的值或异常(如果发生了异常)。
下面以一个说明上面一段文字吧():
// future example
#include &iostream&
// std::cout
#include &future&
// std::async, std::future
#include &chrono&
// std::chrono::milliseconds
// a non-optimized way of checking for prime numbers:
is_prime(int x)
for (int i = 2; i & ++i)
if (x % i == 0)
return false;
return true;
// call function asynchronously:
std::future & bool & fut = std::async(is_prime, );
// do something while waiting for function to set future:
std::cout && "checking, please wait";
std::chrono::milliseconds span(100);
while (fut.wait_for(span) == std::future_status::timeout)
std::cout && '.';
bool x = fut.get();
// retrieve return value
std::cout && "\n " && (x ? "is" : "is not") && " prime.\n";
&std::future 成员函数
std::future 构造函数
std::future 一般由 std::async, std::promise::get_future, std::packaged_task::get_future 创建,不过也提供了构造函数,如下表所示:
default (1)
copy [deleted] (2)
future (const future&) =
future (future&& x)
不过 std::future 的拷贝构造函数是被禁用的,只提供了默认的构造函数和 move 构造函数(注:C++ 新特新)。另外,std::future 的普通赋值操作也被禁用,只提供了 move 赋值操作。如下代码所示:
std::future&int&
// 默认构造函数
fut = std::async(do_some_task);
// move-赋值操作。
std::future::share()
返回一个 std::shared_future 对象(本文后续内容将介绍 std::shared_future ),调用该函数之后,该 std::future 对象本身已经不和任何共享状态相关联,因此该 std::future 的状态不再是 valid 的了。
#include &iostream&
// std::cout
#include &future&
// std::async, std::future, std::shared_future
int do_get_value() { return 10; }
int main ()
std::future&int& fut = std::async(do_get_value);
std::shared_future&int& shared_fut = fut.share();
// 共享的 future 对象可以被多次访问.
std::cout && "value: " && shared_fut.get() && '\n';
std::cout && "its double: " && shared_fut.get()*2 && '\n';
std::future::get()
std::future::get 一共有三种形式,如下表所示():
generic template (1)
reference specialization (2)
R& future&R&&::get();
// when T is a reference type (R&)
void specialization (3)
void future&void&::get();
// when T is void
当与该 std::future 对象相关联的共享状态标志变为 ready 后,调用该函数将返回保存在共享状态中的值,如果共享状态的标志不为 ready,则调用该函数会阻塞当前的调用者,而此后一旦共享状态的标志变为 ready,get 返回 Provider 所设置的共享状态的值或者异常(如果抛出了异常)。
请看下面的程序:
#include &iostream&
// std::cin, std::cout, std::ios
#include &functional&
// std::ref
#include &thread&
// std::thread
#include &future&
// std::promise, std::future
#include &exception&
// std::exception, std::current_exception
void get_int(std::promise&int&& prom) {
std::cout && "Please, enter an integer value: ";
std::cin.exceptions (std::ios::failbit);
// throw on failbit
std::cin &&
// sets failbit if input is not int
prom.set_value(x);
} catch (std::exception&) {
prom.set_exception(std::current_exception());
void print_int(std::future&int&& fut) {
int x = fut.get();
std::cout && "value: " && x && '\n';
} catch (std::exception& e) {
std::cout && "[exception caught: " && e.what() && "]\n";
int main ()
std::promise&int&
std::future&int& fut = prom.get_future();
std::thread th1(get_int, std::ref(prom));
std::thread th2(print_int, std::ref(fut));
th1.join();
th2.join();
std::future::valid()
检查当前的 std::future 对象是否有效,即释放与某个共享状态相关联。一个有效的 std::future 对象只能通过 std::async(), std::future::get_future 或者 std::packaged_task::get_future 来初始化。另外由 std::future 默认构造函数创建的 std::future 对象是无效(invalid)的,当然通过 std::future 的 move 赋值后该 std::future 对象也可以变为 valid。
#include &iostream&
// std::cout
#include &future&
// std::async, std::future
#include &utility&
// std::move
int do_get_value() { return 11; }
int main ()
// 由默认构造函数创建的 std::future 对象,
// 初始化时该 std::future 对象处于为 invalid 状态.
std::future&int& foo,
foo = std::async(do_get_value); // move 赋值, foo 变为 valid.
bar = std::move(foo); // move 赋值, bar 变为 valid, 而 move 赋值以后 foo 变为 invalid.
if (foo.valid())
std::cout && "foo's value: " && foo.get() && '\n';
std::cout && "foo is not valid\n";
if (bar.valid())
std::cout && "bar's value: " && bar.get() && '\n';
std::cout && "bar is not valid\n";
std::future::wait()
等待与当前std::future 对象相关联的共享状态的标志变为 ready.
如果共享状态的标志不是 ready(此时 Provider 没有在共享状态上设置值(或者异常)),调用该函数会被阻塞当前线程,直到共享状态的标志变为 ready。
一旦共享状态的标志变为 ready,wait() 函数返回,当前线程被解除阻塞,但是 wait() 并不读取共享状态的值或者异常。下面的代码说明了 std::future::wait() 的用法()
#include &iostream&
// std::cout
#include &future&
// std::async, std::future
#include &chrono&
// std::chrono::milliseconds
// a non-optimized way of checking for prime numbers:
bool do_check_prime(int x) // 为了体现效果, 该函数故意没有优化.
for (int i = 2; i & ++i)
if (x % i == 0)
return false;
return true;
int main()
// call function asynchronously:
std::future & bool & fut = std::async(do_check_prime, );
std::cout && "Checking...\n";
fut.wait();
std::cout && "\n ";
if (fut.get()) // guaranteed to be ready (and not block) after wait returns
std::cout && "is prime.\n";
std::cout && "is not prime.\n";
执行结果如下:
concurrency ) ./Future-wait
Checking...
concurrency )
std::future::wait_for()
与 std::future::wait() 的功能类似,即等待与该 std::future 对象相关联的共享状态的标志变为 ready,该函数原型如下:
template &class Rep, class Period&
future_status wait_for (const chrono::duration&Rep,Period&& rel_time) const;
而与 std::future::wait() 不同的是,wait_for() 可以设置一个时间段 rel_time,如果共享状态的标志在该时间段结束之前没有被 Provider 设置为 ready,则调用 wait_for 的线程被阻塞,在等待了 rel_time 的时间长度后 wait_until() 返回,返回值如下:
返回值描述
共享状态的标志已经变为 ready,即 Provider 在共享状态上设置了值或者异常。
超时,即在规定的时间内共享状态的标志没有变为 ready。
共享状态包含一个&deferred 函数。
请看下面的例子:
#include &iostream&
// std::cout
#include &future&
// std::async, std::future
#include &chrono&
// std::chrono::milliseconds
// a non-optimized way of checking for prime numbers:
bool do_check_prime(int x) // 为了体现效果, 该函数故意没有优化.
for (int i = 2; i & ++i)
if (x % i == 0)
return false;
return true;
int main()
// call function asynchronously:
std::future & bool & fut = std::async(do_check_prime, );
std::cout && "Checking...\n";
std::chrono::milliseconds span(1000); // 设置超时间隔.
// 如果超时,则输出".",继续等待
while (fut.wait_for(span) == std::future_status::timeout)
std::cout && '.';
std::cout && "\n ";
if (fut.get()) // guaranteed to be ready (and not block) after wait returns
std::cout && "is prime.\n";
std::cout && "is not prime.\n";
std::future::wait_until()
与 std::future::wait() 的功能类似,即等待与该 std::future 对象相关联的共享状态的标志变为 ready,该函数原型如下:
template &class Rep, class Period&
future_status wait_until (const chrono::time_point&Clock,Duration&& abs_time) const;
而 与 std::future::wait() 不同的是,wait_until() 可以设置一个系统绝对时间点 abs_time,如果共享状态的标志在该时间点到来之前没有被 Provider 设置为 ready,则调用 wait_until 的线程被阻塞,在 abs_time 这一时刻到来之后 wait_for() 返回,返回值如下:
返回值描述
共享状态的标志已经变为 ready,即 Provider 在共享状态上设置了值或者异常。
超时,即在规定的时间内共享状态的标志没有变为 ready。
共享状态包含一个&deferred 函数。
std::shared_future 介绍
std::shared_future 与 std::future 类似,但是 std::shared_future 可以拷贝、多个 std::shared_future 可以共享某个共享状态的最终结果(即共享状态的某个值或者异常)。shared_future 可以通过某个 std::future 对象隐式转换(参见 std::shared_future 的构造函数),或者通过 std::future::share() 显示转换,无论哪种转换,被转换的那个 std::future 对象都会变为 not-valid.
std::shared_future 构造函数
std::shared_future 共有四种构造函数,如下表所示:
default (1)
shared_future()
shared_future (const shared_future& x);
shared_future (shared_future&& x)
move from future (4)
shared_future (future&T&&& x)
最后 move from future(4) 即从一个有效的 std::future 对象构造一个 std::shared_future,构造之后 std::future 对象 x 变为无效(not-valid)。
std::shared_future 其他成员函数
std::shared_future 的成员函数和 std::future 大部分相同,如下(每个成员函数都给出了连接):
赋值操作符,与 std::future 的赋值操作不同,std::shared_future 除了支持 move 赋值操作外,还支持普通的赋值操作。获取与该 std::shared_future 对象相关联的共享状态的值(或者异常)。有效性检查。等待与该 std::shared_future 对象相关联的共享状态的标志变为 ready。等待与该 std::shared_future 对象相关联的共享状态的标志变为 ready。(等待一段时间,超过该时间段wait_for 返回。)等待与该 std::shared_future 对象相关联的共享状态的标志变为 ready。(在某一时刻前等待,超过该时刻 wait_until 返回。)
std::future_error 介绍
class future_error : public logic_
std::future_error 继承子 C++ 标准异常体系中的 logic_error,有关 C++ 异常的继承体系,请参考相关的C++教程 ;-)。
其他与 std::future 相关的函数介绍
与 std::future 相关的函数主要是 std::async(),原型如下:
unspecified policy (1)
template &class Fn, class... Args&
future&typename result_of&Fn(Args...)&::type&& & async(Fn&& fn, Args&&... args);
specific policy (2)
template &class Fn, class... Args&
future&typename result_of&Fn(Args...)&::type&& & async(launch policy, Fn&& fn, Args&&... args);
上面两组 std::async() 的不同之处是第一类 std::async 没有指定异步任务(即执行某一函数)的启动策略(launch policy),而第二类函数指定了启动策略,详见 std::launch 枚举类型,指定启动策略的函数的 policy 参数可以是launch::async,launch::deferred,以及两者的按位或( | )。
std::async() 的 fn 和 args 参数用来指定异步任务及其参数。另外,std::async() 返回一个 std::future 对象,通过该对象可以获取异步任务的值或异常(如果异步任务抛出了异常)。
下面介绍一下 std::async 的用法。
#include &stdio.h&
#include &stdlib.h&
#include &cmath&
#include &chrono&
#include &future&
#include &iostream&
double ThreadTask(int n) {
std::cout && std::this_thread::get_id()
&& " start computing..." && std::
double ret = 0;
for (int i = 0; i &= i++) {
ret += std::sin(i);
std::cout && std::this_thread::get_id()
&& " finished computing..." && std::
int main(int argc, const char *argv[])
std::future&double& f(std::async(std::launch::async, ThreadTask, ));
while(f.wait_until(std::chrono::system_clock::now() + std::chrono::seconds(1))
!= std::future_status::ready) {
std::cout && "task is running...\n";
while(f.wait_for(std::chrono::seconds(1))
!= std::future_status::ready) {
std::cout && "task is running...\n";
std::cout && f.get() && std::
return EXIT_SUCCESS;
其他与 std::future 相关的枚举类介绍
下面介绍与 std::future 相关的枚举类型。与 std::future 相关的枚举类型包括:
enum class future_
enum class future_
enum class
下面分别介绍以上三种枚举类型:
std::future_errc 类型
std::future_errc 类型描述如下():
类型取值描述
broken_promise
与该 std::future 共享状态相关联的 std::promise 对象在设置值或者异常之前一被销毁。
future_already_retrieved
与该 std::future 对象相关联的共享状态的值已经被当前 Provider 获取了,即调用了 std::future::get 函数。
promise_already_satisfied
std::promise 对象已经对共享状态设置了某一值或者异常。
无共享状态。
std::future_status 类型()
std::future_status 类型主要用在 std::future(或std::shared_future)中的 wait_for 和 wait_until 两个函数中的。
类型取值描述
wait_for(或wait_until) 因为共享状态的标志变为 ready 而返回。
超时,即 wait_for(或wait_until) 因为在指定的时间段(或时刻)内共享状态的标志依然没有变为 ready 而返回。
共享状态包含了 deferred 函数。
std::launch 类型
该枚举类型主要是在调用 std::async 设置异步任务的启动策略的。
Asynchronous: 异步任务会在另外一个线程中调用,并通过共享状态返回异步任务的结果(一般是调用 std::future::get() 获取异步任务的结果)。
Deferred: 异步任务将会在共享状态被访问时调用,相当与按需调用(即延迟(deferred)调用)。
请看下例():
#include &iostream&
// std::cout
#include &future&
// std::async, std::future, std::launch
#include &chrono&
// std::chrono::milliseconds
#include &thread&
// std::this_thread::sleep_for
do_print_ten(char c, int ms)
for (int i = 0; i & 10; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
std::cout &&
std::cout && "with launch::async:\n";
std::future & void &foo =
std::async(std::launch::async, do_print_ten, '*', 100);
std::future & void &bar =
std::async(std::launch::async, do_print_ten, '@', 200);
// async "get" (wait for foo and bar to be ready):
foo.get();
bar.get();
std::cout && "\n\n";
std::cout && "with launch::deferred:\n";
foo = std::async(std::launch::deferred, do_print_ten, '*', 100);
bar = std::async(std::launch::deferred, do_print_ten, '@', 200);
// deferred "get" (perform the actual calls):
foo.get();
bar.get();
std::cout && '\n';
在我的机器上执行结果:
with launch::async:
*@**@**@**@**@*@@@@@
with launch::deferred:
**********@@@@@@@@@@c++11 并发编程
async promise packaged_task - bw_0927 - 博客园
posts - 9, comments - 32, trackbacks - 0, articles - 1142
http://blog.csdn.net/liuxuejiang158blog/article/details/
A&future&is an object that can retrieve a value from some provider object or function, properly synchronizing this access if in different threads.
future是一个能从其他地方获取到一个值的对象,如果是在不同的线程中,被被synchronizing properly.
std::condition_variable可以用于异步事件的重复通知,但是有些时候可能只等待事件发生一次,比如:等待特定的航班,用条件变量大杀器有点浪费了。C++11标准库提供了几种异步任务机制。通常thread不能返回线程执行的结果(可以通过引用参数返回),而在异步处理当中很多时候都需要获得计算的结果。如果只获取结果一次那么选用future,即通过future获取了结果后,后续再通过此future获取结果将会出错。
(1) future,async,packaged_task,promise用法简介
& & & & &std::future可用于异步任务中获取任务结果,但是它只是获取结果而已,真正的异步调用需要配合std::async, std::promise, std::packaged_task。这里async是个模板函数,promise和packaged_task是模板类,通常模板实例化参数是任务函数(callable object)。下面是它们的部分组合用法:假设计算任务 int task(string x);
& & & & & & & & &1 &async+future简单用法
Call function asynchronouslyCalls&fn&(with&args&as arguments) at some point, returning without waiting for the execution of&fn&to complete.The value returned by&fn&can be accessed through the&&object returned (by calling its member&).A&&object whose&shared state&is made ready when the execution of&fn&ends. The value retrieved by its member&is the value returned by&fn&(if any).
&objects are only useful when they are&.&&&objects are not&&(unless&&a&&).
// future::operator=
#include &iostream&
// std::cout
#include &future&
// std::async, std::future
int get_value() { return 10; }
int main ()
std::future&int&
// default-constructed,默认构造的future对象是无效的
// async()返回的就是一个future对象。 fut = future_returned_by_async(),调用future的赋值运算符。// move-assigned,赋值运算符隐式使用的是move语意(非c++98的拷贝语意), fut = 这使得fut变的有效。同时使得右操作数变的无效
fut = std::async (get_value);
//Calling&&on a&&&blocks the thread until the&provider&makes the&shared state&ready return 0;
std::cout && "value: " && fut.get() && '\n';
future&int&&myFuture=async(task,10)&&&&
& & & & & & & & & & & & //函数立即返回,不会等task执行完毕。async的效果是:自动创建一个后台线程(可以选取一个空闲的线程),将来会在某一时刻执行任务task函数,并将计算结果保存在myFuture中,这里future的模板参数要和任务task返回类型一致为int。怎样获得任务结果呢?通常原来的线程(即创建myFuture的线程记为A,不是async执行task那个线程)可以执行其它操作,直到其想要获取task的结果时调用int x=myFuture.get()即可获得task的执行结果并保存至x中。注意若task没有执行完就调用了myFuture.get()那么线程A将会阻塞直到task完成。
& & & & & & & &
& & & & & & & &2 packaged_task+future简单用法
A&packaged_task&wraps a&callable element&and allows its result to be retrieved asynchronously. &packaged_task用来包裹一个可调用的对象(包括函数,函数指针,函数对象/仿函数,成员函数等)
packaged_task对象包含两个对象:
A&stored task, which is some&callable object&(such as a function pointer, pointer to member or function object) whose&call signature&shall take arguments of the types in&Args...&and return a value of type&Ret.
A&shared state, which is able to store the results of calling the&stored task&(of type&Ret) and be accessed asynchronously through a&.
packaged_task本身不会创建新线程&
packaged_task&int(int)&&myPackaged(task);
future&int&&myFuture=myPackaged.get_future();
thread&myThread(move(myPackaged),"hello&world");
int&x=myFuture.get();
& & & & & & & &3 promise+future简单用法,摘自cplusplus的范例:
#include&&iostream&&&&&&&&//&std::cout&&
#include&&functional&&&&&&//&std::ref&&
#include&&thread&&&&&&&&&&//&std::thread&&
#include&&future&&&&&&&&&&//&std::promise,&std::future&&
void&print_int&(std::future&int&&&fut)&{&&
&&int&x&=&fut.get();
&&std::cout&&&&"value:&"&&&&x&&&&'\n';
int&main&()&&
&&std::promise&int&&&&&&&&&&&&&&&&&&&&&&&&
&&std::future&int&&fut&=&prom.get_future();&&&&
&&std::thread&th1&(print_int,&std::ref(fut));&&
&&prom.set_value&(10);&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&th1.join();
&&return&0;&&
& & & & & & & & & & & & & & //从这个例子可以看出promise+future和前面几个有所不同。
& & & & &将主线程即需要task结果的线程称为provider,称执行任务task或上面print_int的线程为executor(这里只是为了后面表述方便,没有科学考证的)。从上面的例子可以看出,简单的同步机制都是通过设置某种共享状态然后通过future获取该共享状态达到同步。 & &
& & & & & async通过创建或者选取一个当前空闲线程执行任务,然后将计算结果保存至与此async相关的future中,期间只有存取结果值,没有其它的交互,并且是provider持有future,executor执行任务。
& & & & & &packaged_task是一个对象其内部持有callable object,provider创建一个下线程executor执行任务,最后provider通过相关的future获取任务计算结果。和async差不多。只有任务结果的存取,没有其它交互。
& & & & & &promise是provider持有,executor持有相关的future,然后provider通过promise设定共享状态的值,future获取该共享值后执行某些任务。形式上和前面两个有点相反。
(2) 细看future,async,packaged_task,promise
& & & & & &2.1 &future可以获取计算的结果,用于不同线程间的简单同步,future的创建方式:async, packaged_task::get_future , &promise::get_future这三种返回有效的future,这里有效是指future和某个共享状态关联。
future&(const&future&)&=&delete;
future&(future&&&x)&
~future();
future&&operator=&(future&&&rhs)&
future&&operator=&(const&future&)&=&delete;
shared_future&T&&share();
bool&valid()&const&
void&wait()&const;
future_status&wait_for&(const&chrono::duration&Rep,Period&&&rel_time)&const;
future_status&wait_until&(const&chrono::time_point&Clock,Duration&&&abs_time)&const;
future_status:
返回值描述
共享状态的标志已经变为 ready,即 Provider 在共享状态上设置了值或者异常。
超时,即在规定的时间内共享状态的标志没有变为 ready。
共享状态包含一个&deferred&函数。
& & & & & & 2.2 async开启后台线程执行任务
async&(Fn&&&fn,&Args&&...&args);
async&(launch&policy,&Fn&&&fn,&Args&&...&args);
policy=launch::async表示开启一个新的线程执行fn&&
policy=launch::deferred&表示fn推迟到future::wait/get时才执行&&
policy=launch::async|launch::deferred表示由库自动选择哪种机制执行fn,和第一种构造方式async(fn,args)策略相同&&
& & & & & &2.3 packaged_task类似与std::function但是其允许异步存取结果,其内部持有一个函数调用和共享状态,该共享状态可以被packaged_task返回的future获取。
packaged_task()&
explicit&packaged_task&(Fn&&&fn);
explicit&packaged_task&(allocator_arg_t&aa,&const&Alloc&&alloc,&Fn&&&fn);
packaged_task&(const&packaged_task&)&=&delete;
packaged_task&(packaged_task&&&x)&
~packaged_task();
packaged_task&&operator=&(packaged_task&&&rhs)&
ackaged_task&&operator=&(const&packaged_task&)&=&delete;
bool&valid()&const&
future&Ret&&get_future();
void&operator()(Args...&args);
void&make_ready_at_thread_exit&(args...&args);
void&swap&(packaged_task&&x)&
& & & & & 2.4 promise可以存入一个共享状态值,相关的std::future可以获取该值
promise();
template&&class&Alloc&&promise&(allocator_arg_t&aa,&const&Alloc&&alloc);
promise&(const&promise&)&=&delete;
romise&(promise&&&x)&
~promise();
promise&&operator=&(promise&&&rhs)&
promise&&operator=&(const&promise&)&=&delete;&&
future&T&&get_future();
void&set_value&(const&T&&val);
void&set_value&(const&T&&val);&&
void&promise&R&&::set_value&(R&&val);&&&
void&promise&void&::set_value&(void);&&&
void&set_exception&(exception_ptr&p);
void&set_value_at_thread_exit&(const&T&&val);
void&set_value_at_thread_exit&(T&&&val);&&&&&&
void&promise&R&&::set_value_at_thread_exit&(R&&val);&&&&&
void&promise&void&::set_value_at_thread_exit&(void);&&&&&
void&set_exception_at_thread_exit&(exception_ptr&p);
void&swap&(promise&&x)&
& & & & & 2.5 shared_future和future的区别是:一个future对象和一个共享状态相关,且转移只能通过move语义。但是多个shared_future对象可以和共享状态相关(即多对一)。std::shared_future 与 std::future 类似,但是 std::shared_future 可以拷贝、多个 std::shared_future 可以共享某个共享状态的最终结果(即共享状态的某个值或者异常)。shared_future 可以通过某个 std::future 对象隐式转换(参见 std::shared_future 的构造函数),或者通过 std::future::share() 显示转换,无论哪种转换,被转换的那个 std::future 对象都会变为 not-valid.
shared_future()&&&
shared_future&(const&shared_future&&x);&&
shared_future&(shared_future&&&x)&&&
shared_future&(future&T&&&&x)&&&
下面的成员函数和future差不多:&&
operator=&&
&&&赋值操作符,与&std::future&的赋值操作不同,std::shared_future&除了支持&move&赋值操作外,还支持普通的赋值操作。&&
&&&获取与该&std::shared_future&对象相关联的共享状态的值(或者异常)。&&
&&&有效性检查。&&
&&&等待与该&std::shared_future&对象相关联的共享状态的标志变为&ready。&&
wait_for&&
&&&等待与该&std::shared_future&对象相关联的共享状态的标志变为&ready。(等待一段时间,超过该时间段wait_for&返回。)&&
wait_until&&
&&&等待与该&std::shared_future&对象相关联的共享状态的标志变为&ready。(在某一时刻前等待,超过该时刻&wait_until&返回。)&&
&3) 通常线程池采用模板实现时各线程执行的都是相同类型的任务,若采用packaged_task可以将不同类型的函数对象封转在其内部,每个线程取走一个packaged_task执行,那么线程池执行的任务可以不同。
& & & &下面是一个GUI中一个线程专门接收用户任务并压入任务队列,另一个线程专门执行用户任务
std::mutex&m;&&
std::deque&std::packaged_task&void()&&&&&&
bool&gui_shutdown_message_received();&&
void&get_and_process_gui_message();&&
void&gui_thread()&&
&&&while(!gui_shutdown_message_received())
&&&&&&get_and_process_gui_message();&&
&&&&&&std::packaged_task&void()&&&&
&&&&&&&&&&std::lock_guard&std::mutex&&lk(m);&&
&&&&&&&&&&if(tasks.empty())&&
&&&&&&&&&&&&&&continue;&&
&&&&&&&&&&task=std::move(tasks.front());
&&&&&&&&&&tasks.pop_front();&&
&&&&&&task();&&
std::thread&gui_bg_thread(gui_thread);&&
template&typename&Func&&&
std::future&void&&post_task_for_gui_thread(Func&f)
&&&std::packaged_task&void()&&task(f);&&
&&&std::future&void&&res=task.get_future();&&
&&&std::lock_guard&std::mutex&&lk(m);&&
&&&tasks.push_back(std::move(task));
&&&return&&&

我要回帖

更多关于 凌天神帝txt下载 的文章

 

随机推荐