求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 


业务架构设计
4月18-19日 在线直播



基于UML和EA进行系统分析设计
4月25-26日 北京+在线



AI 智能化软件测试方法与实践
5月23-24日 上海+在线
 
追随技术信仰

随时听讲座
每天看新闻
 
 
C++并发编程(中文版)
前言
第1章 你好,C++的并发世界!
1.1 何谓并发
1.2 为什么使用并发?
1.3 C++中的并发和多线程
1.4 开始入门
1.5 本章总结
第2章 线程管理
2.1 线程管理的基础
2.2 向线程函数传递参数
2.3 转移线程所有权
2.4 运行时决定线程数量
2.5 识别线程
2.6 本章总结
第3章 线程间共享数据
3.1 共享数据带来的问题
3.2 使用互斥量保护共享数据
3.3 保护共享数据的替代设施
3.4 本章总结
第4章 同步并发操作
4.1 等待一个事件或其他条件
4.2 使用期望等待一次性事件
4.3 限定等待时间
4.4 使用同步操作简化代码
4.5 本章总结
第5章 C++内存模型和原子类型操作
5.1 内存模型基础
5.2 C++中的原子操作和原子类型
5.3 同步操作和强制排序
5.4 本章总结
第6章 基于锁的并发数据结构设计
6.1 为并发设计的意义何在?
6.2 基于锁的并发数据结构
6.3 基于锁设计更加复杂的数据结构
6.4 本章总结
第7章 无锁并发数据结构设计
7.1 定义和意义
7.2 无锁数据结构的例子
7.3 对于设计无锁数据结构的指导建议
7.4 本章总结
第8章 并发代码设计
8.1 线程间划分工作的技术
8.2 影响并发代码性能的因素
8.3 为多线程性能设计数据结构
8.4 设计并发代码的注意事项
8.5 在实践中设计并发代码
8.6 本章总结
第9章 高级线程管理
9.1 线程池
9.2 中断线程
9.3 本章总结
第10章 多线程程序的测试和调试
10.1 与并发相关的错误类型
10.2 定位并发错误的技术
10.3 本章总结
附录A C++11语言特性简明参考(部分)
A .1 右值引用
A .2 删除函数
A .3 默认函数
A .4 常量表达式函数
A .5 Lambda函数
A .6 变参模板
A .7 自动推导变量类型
A .8 线程本地变量
A .9 本章总结
附录B 并发库的简单比较
附录C 消息传递框架与完整的ATM示例
 附录D C++线程库参考
D .1 chrono头文件
D .2 <condition_variable>头文件
D .3 <atomic>头文件
D .4 future头文件
D .5 <mutex>头文件
D .6 <ratio>头文件
D .7 <thread>头文件
 

 
目录
future头文件
作者:Anthony Williams  译者:陈晓伟
77 次浏览
9次  

D.4 <future>头文件

<future>头文件提供处理异步结果(在其他线程上执行额结果)的工具。

头文件内容

  1. namespace std
  2. {
  3. enum class future_status {
  4. ready, timeout, deferred };
  5. enum class future_errc
  6. {
  7. broken_promise,
  8. future_already_retrieved,
  9. promise_already_satisfied,
  10. no_state
  11. };
  12. class future_error;
  13. const error_category& future_category();
  14. error_code make_error_code(future_errc e);
  15. error_condition make_error_condition(future_errc e);
  16. template<typename ResultType>
  17. class future;
  18. template<typename ResultType>
  19. class shared_future;
  20. template<typename ResultType>
  21. class promise;
  22. template<typename FunctionSignature>
  23. class packaged_task; // no definition provided
  24. template<typename ResultType,typename ... Args>
  25. class packaged_task<ResultType (Args...)>;
  26. enum class launch {
  27. async, deferred
  28. };
  29. template<typename FunctionType,typename ... Args>
  30. future<result_of<FunctionType(Args...)>::type>
  31. async(FunctionType&& func,Args&& ... args);
  32. template<typename FunctionType,typename ... Args>
  33. future<result_of<FunctionType(Args...)>::type>
  34. async(std::launch policy,FunctionType&& func,Args&& ... args);
  35. }

D.4.1 std::future类型模板

std::future类型模板是为了等待其他线程上的异步结果。其和std::promise,std::packaged_task类型模板,还有std::async函数模板,都是为异步结果准备的工具。只有std::future实例可以在任意时间引用异步结果。

std::future实例是MoveConstructible(移动构造)和MoveAssignable(移动赋值),不过不能CopyConstructible(拷贝构造)和CopyAssignable(拷贝赋值)。

类型声明

  1. template<typename ResultType>
  2. class future
  3. {
  4. public:
  5. future() noexcept;
  6. future(future&&) noexcept;
  7. future& operator=(future&&) noexcept;
  8. ~future();
  9. future(future const&) = delete;
  10. future& operator=(future const&) = delete;
  11. shared_future<ResultType> share();
  12. bool valid() const noexcept;
  13. see description get();
  14. void wait();
  15. template<typename Rep,typename Period>
  16. future_status wait_for(
  17. std::chrono::duration<Rep,Period> const& relative_time);
  18. template<typename Clock,typename Duration>
  19. future_status wait_until(
  20. std::chrono::time_point<Clock,Duration> const& absolute_time);
  21. };

std::future 默认构造函数

不使用异步结果构造一个std::future对象。

声明

future() noexcept;

 

效果

构造一个新的std::future实例。

后置条件

valid()返回false。

抛出

std::future 移动构造函数

使用另外一个对象,构造一个std::future对象,将相关异步结果的所有权转移给新std::future对象。

声明

future(future&& other) noexcept;

 

效果

使用已有对象构造一个新的std::future对象。

后置条件

已有对象中的异步结果,将于新的对象相关联。然后,解除已有对象和异步之间的关系。this->valid()返回的结果与之前已有对象other.valid()返回的结果相同。在调用该构造函数后,other.valid()将返回false。

抛出

std::future 移动赋值操作

将已有std::future对象中异步结果的所有权,转移到另一对象当中。

声明

future(future&& other) noexcept;

 

效果

在两个std::future实例中转移异步结果的状态。

后置条件

当执行完赋值操作后,*this.other就与异步结果没有关系了。异步状态(如果有的话)在释放后与*this相关,并且在最后一次引用后,销毁该状态。this->valid()返回的结果与之前已有对象other.valid()返回的结果相同。在调用该构造函数后,other.valid()将返回false。

抛出

std::future 析构函数

销毁一个std::future对象。

声明

~future();

 

效果

销毁*this。如果这是最后一次引用与*this相关的异步结果,之后就会将该异步结果销毁。

抛出

std::future::share 成员函数

构造一个新std::shared_future实例,并且将*this异步结果的所有权转移到新的std::shared_future实例中。

声明

shared_future<ResultType> share();

 

效果

如同 shared_future(std::move(*this))。

后置条件

当调用share()成员函数,与*this相关的异步结果将与新构造的std::shared_future实例相关。this->valid()将返回false。

抛出

std::future::valid 成员函数

检查std::future实例是否与一个异步结果相关联。

声明

bool valid() const noexcept;

 

返回

当与异步结果相关时,返回true,否则返回false。

抛出

std::future::wait 成员函数

如果与*this相关的状态包含延迟函数,将调用该函数。否则,会等待std::future实例中的异步结果准备就绪。

声明

void wait();

 

先决条件

this->valid()将会返回true。

效果

当相关状态包含延迟函数,调用延迟函数,并保存返回的结果,或将抛出的异常保存成为异步结果。否则,会阻塞到*this准备就绪。

抛出

std::future::wait_for 成员函数

等待std::future实例上相关异步结果准备就绪,或超过某个给定的时间。

声明

  1. template<typename Rep,typename Period>
  2. future_status wait_for(
  3. std::chrono::duration<Rep,Period> const& relative_time);

先决条件

this->valid()将会返回true。

效果

如果与*this相关的异步结果包含一个std::async调用的延迟函数(还未执行),那么就不阻塞立即返回。否则将阻塞实例,直到与*this相关异步结果准备就绪,或超过给定的relative_time时长。

返回

当与*this相关的异步结果包含一个std::async调用的延迟函数(还未执行),返回std::future_status::deferred;当与*this相关的异步结果准备就绪,返回std::future_status::ready;当给定时间超过relative_time时,返回std::future_status::timeout。

NOTE:线程阻塞的时间可能超多给定的时长。时长尽可能由一个稳定的时钟决定。

抛出

std::future::wait_until 成员函数

等待std::future实例上相关异步结果准备就绪,或超过某个给定的时间。

声明

  1. template<typename Clock,typename Duration>
  2. future_status wait_until(
  3. std::chrono::time_point<Clock,Duration> const& absolute_time);

先决条件

this->valid()将返回true。

效果

如果与*this相关的异步结果包含一个std::async调用的延迟函数(还未执行),那么就不阻塞立即返回。否则将阻塞实例,直到与*this相关异步结果准备就绪,或Clock::now()返回的时间大于等于absolute_time。

返回

当与*this相关的异步结果包含一个std::async调用的延迟函数(还未执行),返回std::future_status::deferred;当与*this相关的异步结果准备就绪,返回std::future_status::ready;Clock::now()返回的时间大于等于absolute_time,返回std::future_status::timeout。

NOTE:这里不保证调用线程会被阻塞多久,只有函数返回std::future_status::timeout,然后Clock::now()返回的时间大于等于absolute_time的时候,线程才会解除阻塞。

抛出

std::future::get 成员函数

当相关状态包含一个std::async调用的延迟函数,调用该延迟函数,并返回结果;否则,等待与std::future实例相关的异步结果准备就绪,之后返回存储的值或异常。

声明

  1. void future<void>::get();
  2. R& future<R&>::get();
  3. R future<R>::get();

先决条件

this->valid()将返回true。

效果

如果*this相关状态包含一个延期函数,那么调用这个函数并返回结果,或将抛出的异常进行传播。

否则,线程就要被阻塞,直到与*this相关的异步结果就绪。当结果存储了一个异常,那么就就会将存储异常抛出。否则,将会返回存储值。

返回

当相关状态包含一个延期函数,那么这个延期函数的结果将被返回。否则,当ResultType为void时,就会按照常规调用返回。如果ResultType是R&(R类型的引用),存储的引用值将会被返回。否则,存储的值将会返回。

抛出

异常由延期函数,或存储在异步结果中的异常(如果有的话)抛出。

后置条件

this->valid()==false

D.4.2 std::shared_future类型模板

std::shared_future类型模板是为了等待其他线程上的异步结果。其和std::promise,std::packaged_task类型模板,还有std::async函数模板,都是为异步结果准备的工具。多个std::shared_future实例可以引用同一个异步结果。

std::shared_future实例是CopyConstructible(拷贝构造)和CopyAssignable(拷贝赋值)。你也可以同ResultType的std::future类型对象,移动构造一个std::shared_future类型对象。

访问给定std::shared_future实例是非同步的。因此,当有多个线程访问同一个std::shared_future实例,且无任何外围同步操作时,这样的访问是不安全的。不过访问关联状态时是同步的,所以多个线程访问多个独立的std::shared_future实例,且没有外围同步操作的时候,是安全的。

类型定义

  1. template<typename ResultType>
  2. class shared_future
  3. {
  4. public:
  5. shared_future() noexcept;
  6. shared_future(future<ResultType>&&) noexcept;
  7. shared_future(shared_future&&) noexcept;
  8. shared_future(shared_future const&);
  9. shared_future& operator=(shared_future const&);
  10. shared_future& operator=(shared_future&&) noexcept;
  11. ~shared_future();
  12. bool valid() const noexcept;
  13. see description get() const;
  14. void wait() const;
  15. template<typename Rep,typename Period>
  16. future_status wait_for(
  17. std::chrono::duration<Rep,Period> const& relative_time) const;
  18. template<typename Clock,typename Duration>
  19. future_status wait_until(
  20. std::chrono::time_point<Clock,Duration> const& absolute_time)
  21. const;
  22. };

std::shared_future 默认构造函数

不使用关联异步结果,构造一个std::shared_future对象。

声明

shared_future() noexcept;

 

效果

构造一个新的std::shared_future实例。

后置条件

当新实例构建完成后,调用valid()将返回false。

抛出

std::shared_future 移动构造函数

以一个已创建std::shared_future对象为准,构造std::shared_future实例,并将使用std::shared_future对象关联的异步结果的所有权转移到新的实例中。

声明

shared_future(shared_future&& other) noexcept;

 

效果

构造一个新std::shared_future实例。

后置条件

将other对象中关联异步结果的所有权转移到新对象中,这样other对象就没有与之相关联的异步结果了。

抛出

std::shared_future 移动对应std::future对象的构造函数

以一个已创建std::future对象为准,构造std::shared_future实例,并将使用std::shared_future对象关联的异步结果的所有权转移到新的实例中。

声明

shared_future(std::future<ResultType>&& other) noexcept;

 

效果

构造一个std::shared_future对象。

后置条件

将other对象中关联异步结果的所有权转移到新对象中,这样other对象就没有与之相关联的异步结果了。

抛出

std::shared_future 拷贝构造函数

以一个已创建std::future对象为准,构造std::shared_future实例,并将使用std::shared_future对象关联的异步结果(如果有的话)拷贝到新创建对象当中,两个对象共享该异步结果。

声明

shared_future(shared_future const& other);

 

效果

构造一个std::shared_future对象。

后置条件

将other对象中关联异步结果拷贝到新对象中,与other共享关联的异步结果。

抛出

std::shared_future 析构函数

销毁一个std::shared_future对象。

声明

~shared_future();

 

效果

将*this销毁。如果*this关联的异步结果与std::promise或std::packaged_task不再有关联,那么该函数将会切断std::shared_future实例与异步结果的联系,并销毁异步结果。

抛出

std::shared_future::valid 成员函数

检查std::shared_future实例是否与一个异步结果相关联。

声明

bool valid() const noexcept;

 

返回

当与异步结果相关时,返回true,否则返回false。

抛出

std::shared_future::wait 成员函数

当*this关联状态包含一个延期函数,那么调用这个函数。否则,等待直到与std::shared_future实例相关的异步结果就绪为止。

声明

void wait() const;

 

先决条件

this->valid()将返回true。

效果

当有多个线程调用std::shared_future实例上的get()和wait()时,实例会序列化的共享同一关联状态。如果关联状态包括一个延期函数,那么第一个调用get()或wait()时就会调用延期函数,并且存储返回值,或将抛出异常以异步结果的方式保存下来。

抛出

std::shared_future::wait_for 成员函数

等待std::shared_future实例上相关异步结果准备就绪,或超过某个给定的时间。

声明

  1. template<typename Rep,typename Period>
  2. future_status wait_for(
  3. std::chrono::duration<Rep,Period> const& relative_time) const;

先决条件

this->valid()将会返回true。

效果

如果与*this相关的异步结果包含一个std::async调用的延期函数(还未执行),那么就不阻塞立即返回。否则将阻塞实例,直到与*this相关异步结果准备就绪,或超过给定的relative_time时长。

返回

当与*this相关的异步结果包含一个std::async调用的延迟函数(还未执行),返回std::future_status::deferred;当与*this相关的异步结果准备就绪,返回std::future_status::ready;当给定时间超过relative_time时,返回std::future_status::timeout。

NOTE:线程阻塞的时间可能超多给定的时长。时长尽可能由一个稳定的时钟决定。

抛出

std::shared_future::wait_until 成员函数

等待std::future实例上相关异步结果准备就绪,或超过某个给定的时间。

声明

  1. template<typename Clock,typename Duration>
  2. future_status wait_until(
  3. std::chrono::time_point<Clock,Duration> const& absolute_time) const;

先决条件

this->valid()将返回true。

效果

如果与*this相关的异步结果包含一个std::async调用的延迟函数(还未执行),那么就不阻塞立即返回。否则将阻塞实例,直到与*this相关异步结果准备就绪,或Clock::now()返回的时间大于等于absolute_time。

返回

当与*this相关的异步结果包含一个std::async调用的延迟函数(还未执行),返回std::future_status::deferred;当与*this相关的异步结果准备就绪,返回std::future_status::ready;Clock::now()返回的时间大于等于absolute_time,返回std::future_status::timeout。

NOTE:这里不保证调用线程会被阻塞多久,只有函数返回std::future_status::timeout,然后Clock::now()返回的时间大于等于absolute_time的时候,线程才会解除阻塞。

抛出

std::shared_future::get 成员函数

当相关状态包含一个std::async调用的延迟函数,调用该延迟函数,并返回结果;否则,等待与std::shared_future实例相关的异步结果准备就绪,之后返回存储的值或异常。

声明

void shared_future<void>::get() const;

R& shared_future<R&>::get() const;

R const& shared_future<R>::get() const;

 

先决条件

this->valid()将返回true。

效果

当有多个线程调用std::shared_future实例上的get()和wait()时,实例会序列化的共享同一关联状态。如果关联状态包括一个延期函数,那么第一个调用get()或wait()时就会调用延期函数,并且存储返回值,或将抛出异常以异步结果的方式保存下来。

阻塞会知道*this关联的异步结果就绪后解除。当异步结果存储了一个一行,那么就会抛出这个异常。否则,返回存储的值。

返回

当ResultType为void时,就会按照常规调用返回。如果ResultType是R&(R类型的引用),存储的引用值将会被返回。否则,返回存储值的const引用。

抛出

抛出存储的异常(如果有的话)。

D.4.3 std::packaged_task类型模板

std::packaged_task类型模板可打包一个函数或其他可调用对象,所以当函数通过std::packaged_task实例被调用时,结果将会作为异步结果。这个结果可以通过检索std::future实例来查找。

std::packaged_task实例是可以MoveConstructible(移动构造)和MoveAssignable(移动赋值),不过不能CopyConstructible(拷贝构造)和CopyAssignable(拷贝赋值)。

类型定义

  1. template<typename FunctionType>
  2. class packaged_task; // undefined
  3. template<typename ResultType,typename... ArgTypes>
  4. class packaged_task<ResultType(ArgTypes...)>
  5. {
  6. public:
  7. packaged_task() noexcept;
  8. packaged_task(packaged_task&&) noexcept;
  9. ~packaged_task();
  10. packaged_task& operator=(packaged_task&&) noexcept;
  11. packaged_task(packaged_task const&) = delete;
  12. packaged_task& operator=(packaged_task const&) = delete;
  13. void swap(packaged_task&) noexcept;
  14. template<typename Callable>
  15. explicit packaged_task(Callable&& func);
  16. template<typename Callable,typename Allocator>
  17. packaged_task(std::allocator_arg_t, const Allocator&,Callable&&);
  18. bool valid() const noexcept;
  19. std::future<ResultType> get_future();
  20. void operator()(ArgTypes...);
  21. void make_ready_at_thread_exit(ArgTypes...);
  22. void reset();
  23. };

std::packaged_task 默认构造函数

构造一个std::packaged_task对象。

声明

packaged_task() noexcept;

 

效果

不使用关联任务或异步结果来构造一个std::packaged_task对象。

抛出

std::packaged_task 通过可调用对象构造

使用关联任务和异步结果,构造一个std::packaged_task对象。

声明

template<typename Callable>

packaged_task(Callable&& func);

 

先决条件

表达式func(args...)必须是合法的,并且在args...中的args-i参数,必须是ArgTypes...中ArgTypes-i类型的一个值。且返回值必须可转换为ResultType。

效果

使用ResultType类型的关联异步结果,构造一个std::packaged_task对象,异步结果是未就绪的,并且Callable类型相关的任务是对func的一个拷贝。

抛出

当构造函数无法为异步结果分配出内存时,会抛出std::bad_alloc类型的异常。其他异常会在使用Callable类型的拷贝或移动构造过程中抛出。

std::packaged_task 通过有分配器的可调用对象构造

使用关联任务和异步结果,构造一个std::packaged_task对象。使用以提供的分配器为关联任务和异步结果分配内存。

声明

  1. template<typename Allocator,typename Callable>
  2. packaged_task(
  3. std::allocator_arg_t, Allocator const& alloc,Callable&& func);

先决条件

表达式func(args...)必须是合法的,并且在args...中的args-i参数,必须是ArgTypes...中ArgTypes-i类型的一个值。且返回值必须可转换为ResultType。

效果

使用ResultType类型的关联异步结果,构造一个std::packaged_task对象,异步结果是未就绪的,并且Callable类型相关的任务是对func的一个拷贝。异步结果和任务的内存通过内存分配器alloc进行分配,或进行拷贝。

抛出

当构造函数无法为异步结果分配出内存时,会抛出std::bad_alloc类型的异常。其他异常会在使用Callable类型的拷贝或移动构造过程中抛出。

std::packaged_task 移动构造函数

通过一个std::packaged_task对象构建另一个,将与已存在的std::packaged_task相关的异步结果和任务的所有权转移到新构建的对象当中。

声明

packaged_task(packaged_task&& other) noexcept;

 

效果

构建一个新的std::packaged_task实例。

后置条件

通过other构建新的std::packaged_task对象。在新对象构建完成后,other与其之前相关联的异步结果就没有任何关系了。

抛出

std::packaged_task 移动赋值操作

将一个std::packaged_task对象相关的异步结果的所有权转移到另外一个。

声明

packaged_task& operator=(packaged_task&& other) noexcept;

 

效果

将other相关异步结果和任务的所有权转移到*this中,并且切断异步结果和任务与other对象的关联,如同std::packaged_task(other).swap(*this)。

后置条件

与other相关的异步结果与任务移动转移,使*this.other无关联的异步结果。

返回

*this

 

抛出

std::packaged_task::swap 成员函数

将两个std::packaged_task对象所关联的异步结果的所有权进行交换。

声明

void swap(packaged_task& other) noexcept;

 

效果

将other和*this关联的异步结果与任务进行交换。

后置条件

将与other关联的异步结果和任务,通过调用swap的方式,与*this相交换。

抛出

std::packaged_task 析构函数

销毁一个std::packaged_task对象。

声明

~packaged_task();

 

效果

将*this销毁。如果*this有关联的异步结果,并且结果不是一个已存储的任务或异常,那么异步结果状态将会变为就绪,伴随就绪的是一个std::future_error异常和错误码std::future_errc::broken_promise。

抛出

std::packaged_task::get_future 成员函数

在*this相关异步结果中,检索一个std::future实例。

声明

std::future<ResultType> get_future();

 

先决条件

*this具有关联异步结果。

返回

一个与*this关联异构结果相关的一个std::future实例。

抛出

如果一个std::future已经通过get_future()获取了异步结果,在抛出std::future_error异常时,错误码是std::future_errc::future_already_retrieved

std::packaged_task::reset 成员函数

将一个std::packaged_task对实例与一个新的异步结果相关联。

声明

void reset();

 

先决条件

*this具有关联的异步任务。

效果

如同*this=packaged_task(std::move(f)),f是*this中已存储的关联任务。

抛出

如果内存不足以分配给新的异构结果,那么将会抛出std::bad_alloc类异常。

std::packaged_task::valid 成员函数

检查*this中是都具有关联任务和异步结果。

声明

bool valid() const noexcept;

 

返回

当*this具有相关任务和异步结构,返回true;否则,返回false。

抛出

std::packaged_task::operator() 函数调用操作

调用一个std::packaged_task实例中的相关任务,并且存储返回值,或将异常存储到异常结果当中。

声明

void operator()(ArgTypes... args);

 

先决条件

*this具有相关任务。

效果

像INVOKE(func,args...)那要调用相关的函数func。如果返回征程,那么将会存储到this相关的异步结果中。当返回结果是一个异常,将这个异常存储到this相关的异步结果中。

后置条件

*this相关联的异步结果状态为就绪,并且存储了一个值或异常。所有阻塞线程,在等待到异步结果的时候被解除阻塞。

抛出

当异步结果已经存储了一个值或异常,那么将抛出一个std::future_error异常,错误码为std::future_errc::promise_already_satisfied。

同步

std::future<ResultType>::get()或std::shared_future<ResultType>::get()的成功调用,代表同步操作的成功,函数将会检索异步结果中的值或异常。

std::packaged_task::make_ready_at_thread_exit 成员函数

调用一个std::packaged_task实例中的相关任务,并且存储返回值,或将异常存储到异常结果当中,直到线程退出时,将相关异步结果的状态置为就绪。

声明

void make_ready_at_thread_exit(ArgTypes... args);

 

先决条件

*this具有相关任务。

效果

像INVOKE(func,args...)那要调用相关的函数func。如果返回征程,那么将会存储到*this相关的异步结果中。当返回结果是一个异常,将这个异常存储到*this相关的异步结果中。当当前线程退出的时候,可调配相关异步状态为就绪。

后置条件

*this的异步结果中已经存储了一个值或一个异常,不过在当前线程退出的时候,这个结果都是非就绪的。当当前线程退出时,阻塞等待异步结果的线程将会被解除阻塞。

抛出

当异步结果已经存储了一个值或异常,那么将抛出一个std::future_error异常,错误码为std::future_errc::promise_already_satisfied。当无关联异步状态时,抛出std::future_error异常,错误码为std::future_errc::no_state。

同步

std::future<ResultType>::get()或std::shared_future<ResultType>::get()在线程上的成功调用,代表同步操作的成功,函数将会检索异步结果中的值或异常。

D.4.4 std::promise类型模板

std::promise类型模板提供设置异步结果的方法,这样其他线程就可以通过std::future实例来索引该结果。

ResultType模板参数,该类型可以存储异步结果。

std::promise实例中的异步结果与某个srd::future实例相关联,并且可以通过调用get_future()成员函数来获取这个srd::future实例。ResultType类型的异步结果,可以通过set_value()成员函数对存储值进行设置,或者使用set_exception()将对应异常设置进异步结果中。

std::promise实例是可以MoveConstructible(移动构造)和MoveAssignable(移动赋值),但是不能CopyConstructible(拷贝构造)和CopyAssignable(拷贝赋值)。

类型定义

  1. template<typename ResultType>
  2. class promise
  3. {
  4. public:
  5. promise();
  6. promise(promise&&) noexcept;
  7. ~promise();
  8. promise& operator=(promise&&) noexcept;
  9. template<typename Allocator>
  10. promise(std::allocator_arg_t, Allocator const&);
  11. promise(promise const&) = delete;
  12. promise& operator=(promise const&) = delete;
  13. void swap(promise& ) noexcept;
  14. std::future<ResultType> get_future();
  15. void set_value(see description);
  16. void set_exception(std::exception_ptr p);
  17. };

std::promise 默认构造函数

构造一个std::promise对象。

声明

promise();

 

效果

使用ResultType类型的相关异步结果来构造std::promise实例,不过异步结果并未就绪。

抛出

当没有足够内存为异步结果进行分配,那么将抛出std::bad_alloc型异常。

std::promise 带分配器的构造函数

构造一个std::promise对象,使用提供的分配器来为相关异步结果分配内存。

声明

template<typename Allocator>

promise(std::allocator_arg_t, Allocator const& alloc);

 

效果

使用ResultType类型的相关异步结果来构造std::promise实例,不过异步结果并未就绪。异步结果的内存由alloc分配器来分配。

抛出

当分配器为异步结果分配内存时,如有抛出异常,就为该函数抛出的异常。

std::promise 移动构造函数

通过另一个已存在对象,构造一个std::promise对象。将已存在对象中的相关异步结果的所有权转移到新创建的std::promise对象当中。

声明

promise(promise&& other) noexcept;

 

效果

构造一个std::promise实例。

后置条件

当使用other来构造一个新的实例,那么other中相关异构结果的所有权将转移到新创建的对象上。之后,other将无关联异步结果。

抛出

std::promise 移动赋值操作符

在两个std::promise实例中转移异步结果的所有权。

声明

promise& operator=(promise&& other) noexcept;

 

效果

在other和*this之间进行异步结果所有权的转移。当*this已经有关联的异步结果,那么该异步结果的状态将会为就绪态,且伴随一个std::future_error类型异常,错误码为std::future_errc::broken_promise。

后置条件

将other中关联的异步结果转移到*this当中。other中将无关联异步结果。

返回

*this

 

抛出

std::promise::swap 成员函数

将两个std::promise实例中的关联异步结果进行交换。

声明

void swap(promise& other);

 

效果

交换other和*this当中的关联异步结果。

后置条件

当swap使用other时,other中的异步结果就会与*this中关联异步结果相交换。二者返回来亦然。

抛出

std::promise 析构函数

销毁std::promise对象。

声明

~promise();

效果

销毁*this。当*this具有关联的异步结果,并且结果中没有存储值或异常,那么结果将会置为就绪,伴随一个std::future_error异常,错误码为std::future_errc::broken_promise。

抛出

std::promise::get_future 成员函数

通过*this关联的异步结果,检索出所要的std::future实例。

声明

std::future<ResultType> get_future();

先决条件

*this具有关联异步结果。

返回

与*this关联异步结果关联的std::future实例。

抛出

当std::future已经通过get_future()获取过了,将会抛出一个std::future_error类型异常,伴随的错误码为std::future_errc::future_already_retrieved。

std::promise::set_value 成员函数

存储一个值到与*this关联的异步结果中。

声明

void promise<void>::set_value();
void promise<R&>::set_value(R& r);
void promise<R>::set_value(R const& r);
void promise<R>::set_value(R&& r);

先决条件

*this具有关联异步结果。

效果

当ResultType不是void型,就存储r到*this相关的异步结果当中。

后置条件

*this相关的异步结果的状态为就绪,且将值存入。任意等待异步结果的阻塞线程将

 

 


您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码: 验证码,看不清楚?请点击刷新验证码 必填



77 次浏览
9次