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


DeepSeek大模型应用开发实践
6月12-13日 厦门



基于 UML 和EA进行分析设计
6月23-24日 北京+线上



人工智能、机器学习& TensorFlow+Keras
6月22-23日 北京
 
追随技术信仰

随时听讲座
每天看新闻
 
 
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>头文件
 

 
目录
<condition_variable>头文件
作者:Anthony Williams  译者:陈晓伟
178 次浏览
7次  

D.2 头文件

<condition_variable>头文件提供了条件变量的定义。其作为基本同步机制,允许被阻塞的线程在某些条件达成或超时时,解除阻塞继续执行。

头文件内容

  1. namespace std
  2. {
  3. enum class cv_status { timeout, no_timeout };
  4. class condition_variable;
  5. class condition_variable_any;
  6. }

 

D.2.1 std::condition_variable类

std::condition_variable允许阻塞一个线程,直到条件达成。

std::condition_variable实例不支持CopyAssignable(拷贝赋值), CopyConstructible(拷贝构造), MoveAssignable(移动赋值)和 MoveConstructible(移动构造)。

类型定义

  1. class condition_variable
  2. {
  3. public:
  4. condition_variable();
  5. ~condition_variable();
  6. condition_variable(condition_variable const& ) = delete;
  7. condition_variable& operator=(condition_variable const& ) = delete;
  8. void notify_one() noexcept;
  9. void notify_all() noexcept;
  10. void wait(std::unique_lock<std::mutex>& lock);
  11. template <typename Predicate>
  12. void wait(std::unique_lock<std::mutex>& lock,Predicate pred);
  13. template <typename Clock, typename Duration>
  14. cv_status wait_until(
  15. std::unique_lock<std::mutex>& lock,
  16. const std::chrono::time_point<Clock, Duration>& absolute_time);
  17. template <typename Clock, typename Duration, typename Predicate>
  18. bool wait_until(
  19. std::unique_lock<std::mutex>& lock,
  20. const std::chrono::time_point<Clock, Duration>& absolute_time,
  21. Predicate pred);
  22. template <typename Rep, typename Period>
  23. cv_status wait_for(
  24. std::unique_lock<std::mutex>& lock,
  25. const std::chrono::duration<Rep, Period>& relative_time);
  26. template <typename Rep, typename Period, typename Predicate>
  27. bool wait_for(
  28. std::unique_lock<std::mutex>& lock,
  29. const std::chrono::duration<Rep, Period>& relative_time,
  30. Predicate pred);
  31. };
  32. void notify_all_at_thread_exit(condition_variable&,unique_lock<mutex>);

 

std::condition_variable 默认构造函数

构造一个std::condition_variable对象。

声明

condition_variable();

 

效果

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

抛出

当条件变量无法够早的时候,将会抛出一个std::system_error异常。

std::condition_variable 析构函数

销毁一个std::condition_variable对象。

声明

~condition_variable();

 

先决条件

之前没有使用*this总的wait(),wait_for()或wait_until()阻塞过线程。

效果

销毁*this。

抛出

std::condition_variable::notify_one 成员函数

唤醒一个等待当前std::condition_variable实例的线程。

声明

void notify_one() noexcept;

 

效果

唤醒一个等待*this的线程。如果没有线程在等待,那么调用没有任何效果。

抛出

当效果没有达成,就会抛出std::system_error异常。

同步

std::condition_variable实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable::notify_all 成员函数

唤醒所有等待当前std::condition_variable实例的线程。

声明

void notify_all() noexcept;

 

效果

唤醒所有等待*this的线程。如果没有线程在等待,那么调用没有任何效果。

抛出

当效果没有达成,就会抛出std::system_error异常

同步

std::condition_variable实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable::wait 成员函数

通过std::condition_variable的notify_one()、notify_all()或伪唤醒结束等待。

等待

void wait(std::unique_lock<std::mutex>& lock);

 

先决条件

当线程调用wait()即可获得锁的所有权,lock.owns_lock()必须为true。

效果

自动解锁lock对象,对于线程等待线程,当其他线程调用notify_one()或notify_all()时被唤醒,亦或该线程处于伪唤醒状态。在wait()返回前,lock对象将会再次上锁。

抛出

当效果没有达成的时候,将会抛出std::system_error异常。当lock对象在调用wait()阶段被解锁,那么当wait()退出的时候lock会再次上锁,即使函数是通过异常的方式退出。

NOTE:伪唤醒意味着一个线程调用wait()后,在没有其他线程调用notify_one()或notify_all()时,还处以苏醒状态。因此,建议对wait()进行重载,在可能的情况下使用一个谓词。否则,建议wait()使用循环检查与条件变量相关的谓词。

同步

std::condition_variable实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable::wait 需要一个谓词的成员函数重载

等待std::condition_variable上的notify_one()或notify_all()被调用,或谓词为true的情况,来唤醒线程。

声明

  1. template<typename Predicate>
  2. void wait(std::unique_lock<std::mutex>& lock,Predicate pred);

先决条件

pred()谓词必须是合法的,并且需要返回一个值,这个值可以和bool互相转化。当线程调用wait()即可获得锁的所有权,lock.owns_lock()必须为true。

效果

正如

  1. while(!pred())
  2. {
  3. wait(lock);
  4. }

抛出

pred中可以抛出任意异常,或者当效果没有达到的时候,抛出std::system_error异常。

NOTE:潜在的伪唤醒意味着不会指定pred调用的次数。通过lock进行上锁,pred经常会被互斥量引用所调用,并且函数必须返回(只能返回)一个值,在(bool)pred()评估后,返回true。

同步

std::condition_variable实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable::wait_for 成员函数

std::condition_variable在调用notify_one()、调用notify_all()、超时或线程伪唤醒时,结束等待。

声明

  1. template<typename Rep,typename Period>
  2. cv_status wait_for(
  3. std::unique_lock<std::mutex>& lock,
  4. std::chrono::duration<Rep,Period> const& relative_time);

先决条件

当线程调用wait()即可获得锁的所有权,lock.owns_lock()必须为true。

效果

当其他线程调用notify_one()或notify_all()函数时,或超出了relative_time的时间,亦或是线程被伪唤醒,则将lock对象自动解锁,并将阻塞线程唤醒。当wait_for()调用返回前,lock对象会再次上锁。

返回

线程被notify_one()、notify_all()或伪唤醒唤醒时,会返回std::cv_status::no_timeout;反之,则返回std::cv_status::timeout。

抛出

当效果没有达成的时候,会抛出std::system_error异常。当lock对象在调用wait_for()函数前解锁,那么lock对象会在wait_for()退出前再次上锁,即使函数是以异常的方式退出。

NOTE:伪唤醒意味着,一个线程在调用wait_for()的时候,即使没有其他线程调用notify_one()和notify_all()函数,也处于苏醒状态。因此,这里建议重载wait_for()函数,重载函数可以使用谓词。要不,则建议wait_for()使用循环的方式对与谓词相关的条件变量进行检查。在这样做的时候还需要小心,以确保超时部分依旧有效;wait_until()可能适合更多的情况。这样的话,线程阻塞的时间就要比指定的时间长了。在有这样可能性的地方,流逝的时间是由稳定时钟决定。

同步

std::condition_variable实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable::wait_for 需要一个谓词的成员函数重载

std::condition_variable在调用notify_one()、调用notify_all()、超时或线程伪唤醒时,结束等待。

声明

  1. template<typename Rep,typename Period,typename Predicate>
  2. bool wait_for(
  3. std::unique_lock<std::mutex>& lock,
  4. std::chrono::duration<Rep,Period> const& relative_time,
  5. Predicate pred);

先决条件

pred()谓词必须是合法的,并且需要返回一个值,这个值可以和bool互相转化。当线程调用wait()即可获得锁的所有权,lock.owns_lock()必须为true。

效果

等价于

  1. internal_clock::time_point end=internal_clock::now()+relative_time;
  2. while(!pred())
  3. {
  4. std::chrono::duration<Rep,Period> remaining_time=
  5. end-internal_clock::now();
  6. if(wait_for(lock,remaining_time)==std::cv_status::timeout)
  7. return pred();
  8. }
  9. return true;

返回

当pred()为true,则返回true;当超过relative_time并且pred()返回false时,返回false。

NOTE:潜在的伪唤醒意味着不会指定pred调用的次数。通过lock进行上锁,pred经常会被互斥量引用所调用,并且函数必须返回(只能返回)一个值,在(bool)pred()评估后返回true,或在指定时间relative_time内完成。线程阻塞的时间就要比指定的时间长了。在有这样可能性的地方,流逝的时间是由稳定时钟决定。

抛出

当效果没有达成时,会抛出std::system_error异常或者由pred抛出任意异常。

同步

std::condition_variable实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable::wait_until 成员函数

std::condition_variable在调用notify_one()、调用notify_all()、指定时间内达成条件或线程伪唤醒时,结束等待。

声明

  1. template<typename Clock,typename Duration>
  2. cv_status wait_until(
  3. std::unique_lock<std::mutex>& lock,
  4. std::chrono::time_point<Clock,Duration> const& absolute_time);

先决条件

当线程调用wait()即可获得锁的所有权,lock.owns_lock()必须为true。

效果

当其他线程调用notify_one()或notify_all()函数,或Clock::now()返回一个大于或等于absolute_time的时间,亦或线程伪唤醒,lock都将自动解锁,并且唤醒阻塞的线程。在wait_until()返回之前lock对象会再次上锁。

返回

线程被notify_one()、notify_all()或伪唤醒唤醒时,会返回std::cv_status::no_timeout;反之,则返回std::cv_status::timeout。

抛出

当效果没有达成的时候,会抛出std::system_error异常。当lock对象在调用wait_for()函数前解锁,那么lock对象会在wait_for()退出前再次上锁,即使函数是以异常的方式退出。

NOTE:伪唤醒意味着一个线程调用wait()后,在没有其他线程调用notify_one()或notify_all()时,还处以苏醒状态。因此,这里建议重载wait_until()函数,重载函数可以使用谓词。要不,则建议wait_until()使用循环的方式对与谓词相关的条件变量进行检查。这里不保证线程会被阻塞多长时间,只有当函数返回false后(Clock::now()的返回值大于或等于absolute_time),线程才能解除阻塞。

同步

std::condition_variable实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable::wait_until 需要一个谓词的成员函数重载

std::condition_variable在调用notify_one()、调用notify_all()、谓词返回true或指定时间内达到条件,结束等待。

声明

  1. template<typename Clock,typename Duration,typename Predicate>
  2. bool wait_until(
  3. std::unique_lock<std::mutex>& lock,
  4. std::chrono::time_point<Clock,Duration> const& absolute_time,
  5. Predicate pred);

先决条件

pred()必须是合法的,并且其返回值能转换为bool值。当线程调用wait()即可获得锁的所有权,lock.owns_lock()必须为true。

效果

等价于

  1. while(!pred())
  2. {
  3. if(wait_until(lock,absolute_time)==std::cv_status::timeout)
  4. return pred();
  5. }
  6. return true;

 

返回

当调用pred()返回true时,返回true;当Clock::now()的时间大于或等于指定的时间absolute_time,并且pred()返回false时,返回false。

NOTE:潜在的伪唤醒意味着不会指定pred调用的次数。通过lock进行上锁,pred经常会被互斥量引用所调用,并且函数必须返回(只能返回)一个值,在(bool)pred()评估后返回true,或Clock::now()返回的时间大于或等于absolute_time。这里不保证调用线程将被阻塞的时长,只有当函数返回false后(Clock::now()返回一个等于或大于absolute_time的值),线程接触阻塞。

抛出

当效果没有达成时,会抛出std::system_error异常或者由pred抛出任意异常。

同步

std::condition_variable实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::notify_all_at_thread_exit 非成员函数

当当前调用函数的线程退出时,等待std::condition_variable的所有线程将会被唤醒。

声明

  1. void notify_all_at_thread_exit(
  2. condition_variable& cv,unique_lock<mutex> lk);

先决条件

当线程调用wait()即可获得锁的所有权,lk.owns_lock()必须为true。lk.mutex()需要返回的值要与并发等待线程相关的任意cv中锁对象提供的wait(),wait_for()或wait_until()相同。

效果

将lk的所有权转移到内部存储中,并且当有线程退出时,安排被提醒的cv类。这里的提醒等价于

  1. lk.unlock();
  2. cv.notify_all();

抛出

当效果没有达成时,抛出std::system_error异常。

NOTE:在线程退出前,掌握着锁的所有权,所以这里要避免死锁发生。这里建议调用该函数的线程应该尽快退出,并且在该线程可以执行一些阻塞的操作。用户必须保证等地线程不会错误的将唤醒线程当做已退出的线程,特别是伪唤醒。可以通过等待线程上的谓词测试来实现这一功能,在互斥量保护的情况下,只有谓词返回true时线程才能被唤醒,并且在调用notify_all_at_thread_exit(std::condition_variable_any类中函数)前是不会释放锁。

D.2.2 std::condition_variable_any类

std::condition_variable_any类允许线程等待某一条件为true的时候继续运行。不过std::condition_variable只能和std::unique_lock<std::mutex>一起使用,std::condition_variable_any可以和任意可上锁(Lockable)类型一起使用。

std::condition_variable_any实例不能进行拷贝赋值(CopyAssignable)、拷贝构造(CopyConstructible)、移动赋值(MoveAssignable)或移动构造(MoveConstructible)。

类型定义

  1. class condition_variable_any
  2. {
  3. public:
  4. condition_variable_any();
  5. ~condition_variable_any();
  6. condition_variable_any(
  7. condition_variable_any const& ) = delete;
  8. condition_variable_any& operator=(
  9. condition_variable_any const& ) = delete;
  10. void notify_one() noexcept;
  11. void notify_all() noexcept;
  12. template<typename Lockable>
  13. void wait(Lockable& lock);
  14. template <typename Lockable, typename Predicate>
  15. void wait(Lockable& lock, Predicate pred);
  16. template <typename Lockable, typename Clock,typename Duration>
  17. std::cv_status wait_until(
  18. Lockable& lock,
  19. const std::chrono::time_point<Clock, Duration>& absolute_time);
  20. template <
  21. typename Lockable, typename Clock,
  22. typename Duration, typename Predicate>
  23. bool wait_until(
  24. Lockable& lock,
  25. const std::chrono::time_point<Clock, Duration>& absolute_time,
  26. Predicate pred);
  27. template <typename Lockable, typename Rep, typename Period>
  28. std::cv_status wait_for(
  29. Lockable& lock,
  30. const std::chrono::duration<Rep, Period>& relative_time);
  31. template <
  32. typename Lockable, typename Rep,
  33. typename Period, typename Predicate>
  34. bool wait_for(
  35. Lockable& lock,
  36. const std::chrono::duration<Rep, Period>& relative_time,
  37. Predicate pred);
  38. };

 

std::condition_variable_any 默认构造函数

构造一个std::condition_variable_any对象。

声明

condition_variable_any();

 

效果

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

抛出

当条件变量构造成功,将抛出std::system_error异常。

std::condition_variable_any 析构函数

销毁std::condition_variable_any对象。

声明

~condition_variable_any();

 

先决条件

之前没有使用*this总的wait(),wait_for()或wait_until()阻塞过线程。

效果

销毁*this。

抛出

std::condition_variable_any::notify_one 成员函数

std::condition_variable_any唤醒一个等待该条件变量的线程。

声明

void notify_all() noexcept;

 

效果

唤醒一个等待*this的线程。如果没有线程在等待,那么调用没有任何效果

抛出

当效果没有达成,就会抛出std::system_error异常。

同步

std::condition_variable实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable_any::notify_all 成员函数

唤醒所有等待当前std::condition_variable_any实例的线程。

声明

void notify_all() noexcept;

效果

唤醒所有等待*this的线程。如果没有线程在等待,那么调用没有任何效果

抛出

当效果没有达成,就会抛出std::system_error异常。

同步

std::condition_variable实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable_any::wait 成员函数

通过std::condition_variable_any的notify_one()、notify_all()或伪唤醒结束等待。

声明

  1. template<typename Lockable>
  2. void wait(Lockable& lock);

先决条件

Lockable类型需要能够上锁,lock对象拥有一个锁。

效果

自动解锁lock对象,对于线程等待线程,当其他线程调用notify_one()或notify_all()时被唤醒,亦或该线程处于伪唤醒状态。在wait()返回前,lock对象将会再次上锁。

抛出

当效果没有达成的时候,将会抛出std::system_error异常。当lock对象在调用wait()阶段被解锁,那么当wait()退出的时候lock会再次上锁,即使函数是通过异常的方式退出。

NOTE:伪唤醒意味着一个线程调用wait()后,在没有其他线程调用notify_one()或notify_all()时,还处以苏醒状态。因此,建议对wait()进行重载,在可能的情况下使用一个谓词。否则,建议wait()使用循环检查与条件变量相关的谓词。

同步

std::condition_variable_any实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable_any::wait 需要一个谓词的成员函数重载

等待std::condition_variable_any上的notify_one()或notify_all()被调用,或谓词为true的情况,来唤醒线程。

声明

  1. template<typename Lockable,typename Predicate>
  2. void wait(Lockable& lock,Predicate pred);

先决条件

pred()谓词必须是合法的,并且需要返回一个值,这个值可以和bool互相转化。当线程调用wait()即可获得锁的所有权,lock.owns_lock()必须为true。

效果

正如

  1. while(!pred())
  2. {
  3. wait(lock);
  4. }

抛出

pred中可以抛出任意异常,或者当效果没有达到的时候,抛出std::system_error异常。

NOTE:潜在的伪唤醒意味着不会指定pred调用的次数。通过lock进行上锁,pred经常会被互斥量引用所调用,并且函数必须返回(只能返回)一个值,在(bool)pred()评估后,返回true。

同步

std::condition_variable_any实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable_any::wait_for 成员函数

std::condition_variable_any在调用notify_one()、调用notify_all()、超时或线程伪唤醒时,结束等待。

声明

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

先决条件

当线程调用wait()即可获得锁的所有权,lock.owns_lock()必须为true。

效果

当其他线程调用notify_one()或notify_all()函数时,或超出了relative_time的时间,亦或是线程被伪唤醒,则将lock对象自动解锁,并将阻塞线程唤醒。当wait_for()调用返回前,lock对象会再次上锁。

返回

线程被notify_one()、notify_all()或伪唤醒唤醒时,会返回std::cv_status::no_timeout;反之,则返回std::cv_status::timeout。

抛出

当效果没有达成的时候,会抛出std::system_error异常。当lock对象在调用wait_for()函数前解锁,那么lock对象会在wait_for()退出前再次上锁,即使函数是以异常的方式退出。

NOTE:伪唤醒意味着,一个线程在调用wait_for()的时候,即使没有其他线程调用notify_one()和notify_all()函数,也处于苏醒状态。因此,这里建议重载wait_for()函数,重载函数可以使用谓词。要不,则建议wait_for()使用循环的方式对与谓词相关的条件变量进行检查。在这样做的时候还需要小心,以确保超时部分依旧有效;wait_until()可能适合更多的情况。这样的话,线程阻塞的时间就要比指定的时间长了。在有这样可能性的地方,流逝的时间是由稳定时钟决定。

同步

std::condition_variable_any实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable_any::wait_for 需要一个谓词的成员函数重载

std::condition_variable_any在调用notify_one()、调用notify_all()、超时或线程伪唤醒时,结束等待。

声明

  1. template<typename Lockable,typename Rep,
  2. typename Period, typename Predicate>
  3. bool wait_for(
  4. Lockable& lock,
  5. std::chrono::duration<Rep,Period> const& relative_time,
  6. Predicate pred);

先决条件

pred()谓词必须是合法的,并且需要返回一个值,这个值可以和bool互相转化。当线程调用wait()即可获得锁的所有权,lock.owns_lock()必须为true。

效果

正如

  1. internal_clock::time_point end=internal_clock::now()+relative_time;
  2. while(!pred())
  3. {
  4. std::chrono::duration<Rep,Period> remaining_time=
  5. end-internal_clock::now();
  6. if(wait_for(lock,remaining_time)==std::cv_status::timeout)
  7. return pred();
  8. }
  9. return true;

 

返回

当pred()为true,则返回true;当超过relative_time并且pred()返回false时,返回false。

NOTE:

潜在的伪唤醒意味着不会指定pred调用的次数。通过lock进行上锁,pred经常会被互斥量引用所调用,并且函数必须返回(只能返回)一个值,在(bool)pred()评估后返回true,或在指定时间relative_time内完成。线程阻塞的时间就要比指定的时间长了。在有这样可能性的地方,流逝的时间是由稳定时钟决定。

抛出

当效果没有达成时,会抛出std::system_error异常或者由pred抛出任意异常。

同步

std::condition_variable_any实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable_any::wait_until 成员函数

std::condition_variable_any在调用notify_one()、调用notify_all()、指定时间内达成条件或线程伪唤醒时,结束等待

声明

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

先决条件

Lockable类型需要能够上锁,lock对象拥有一个锁。

效果

当其他线程调用notify_one()或notify_all()函数,或Clock::now()返回一个大于或等于absolute_time的时间,亦或线程伪唤醒,lock都将自动解锁,并且唤醒阻塞的线程。在wait_until()返回之前lock对象会再次上锁。

返回

线程被notify_one()、notify_all()或伪唤醒唤醒时,会返回std::cv_status::no_timeout;反之,则返回std::cv_status::timeout。

抛出

当效果没有达成的时候,会抛出std::system_error异常。当lock对象在调用wait_for()函数前解锁,那么lock对象会在wait_for()退出前再次上锁,即使函数是以异常的方式退出。

NOTE:伪唤醒意味着一个线程调用wait()后,在没有其他线程调用notify_one()或notify_all()时,还处以苏醒状态。因此,这里建议重载wait_until()函数,重载函数可以使用谓词。要不,则建议wait_until()使用循环的方式对与谓词相关的条件变量进行检查。这里不保证线程会被阻塞多长时间,只有当函数返回false后(Clock::now()的返回值大于或等于absolute_time),线程才能解除阻塞。

同步

std::condition_variable_any实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

std::condition_variable_any::wait_unti 需要一个谓词的成员函数重载

std::condition_variable_any在调用notify_one()、调用notify_all()、谓词返回true或指定时间内达到条件,结束等待。

声明

  1. template<typename Lockable,typename Clock,
  2. typename Duration, typename Predicate>
  3. bool wait_until(
  4. Lockable& lock,
  5. std::chrono::time_point<Clock,Duration> const& absolute_time,
  6. Predicate pred);

先决条件

pred()必须是合法的,并且其返回值能转换为bool值。当线程调用wait()即可获得锁的所有权,lock.owns_lock()必须为true。

效果

等价于

  1. while(!pred())
  2. {
  3. if(wait_until(lock,absolute_time)==std::cv_status::timeout)
  4. return pred();
  5. }
  6. return true;

 

返回

当调用pred()返回true时,返回true;当Clock::now()的时间大于或等于指定的时间absolute_time,并且pred()返回false时,返回false。

NOTE:潜在的伪唤醒意味着不会指定pred调用的次数。通过lock进行上锁,pred经常会被互斥量引用所调用,并且函数必须返回(只能返回)一个值,在(bool)pred()评估后返回true,或Clock::now()返回的时间大于或等于absolute_time。这里不保证调用线程将被阻塞的时长,只有当函数返回false后(Clock::now()返回一个等于或大于absolute_time的值),线程接触阻塞。

抛出

当效果没有达成时,会抛出std::system_error异常或者由pred抛出任意异常。

同步

std::condition_variable_any实例中的notify_one(),notify_all(),wait(),wait_for()和wait_until()都是序列化函数(串行调用)。调用notify_one()或notify_all()只能唤醒正在等待中的线程。

 

 


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

1元 10元 50元





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



178 次浏览
7次