thread_condition.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /* Thread_condition 是多线程的条件控制类,主要是控制线程的启停和退出
  2. * 线程创建后,一般是循环运行,
  3. * 为了防止线程暂满整个cpu,那么需要线程在不工作的是否进入等待状态。
  4. * Thread_condition 就可以控制线程的运行状态。
  5. *
  6. std::atomic<bool> m_pass_ever //线程能否直接通过等待,对后面的线程也生效。
  7. std::atomic<bool> m_pass_once //线程能否直接通过等待,一次(通过一次之后,wait里面自动改为false)
  8. * 外部调用notify系列的函数,唤醒等待的线程,让线程执行功能函数。
  9. * 如果需要线程循环多次执行功能函数,那么就使用 notify_all(true),后面的线程可以直接通过等待了。
  10. * 再使用 notify_all(false) ,即可停止线程,让其继续等待。
  11. * 如果只想要线程执行一次,那就使用 notify_all(false, true)
  12. * 注:notify_all(false, true)和notify_one(false, true) 一样,只能让其中一个线程执行一次
  13. *
  14. * m_kill_flag //是否杀死线程,让线程强制退出,
  15. * 外部调用 kill_all() 函数,可以直接通知线程自动退出。
  16. //杀死所有的线程,强制退出线程函数,只是操作受当前Thread_condition影响的所有线程
  17. //唤醒所有线程,使其通过等待,但是不能运行功能函数,必须直接return
  18. // 注:只是修改m_kill为true,需要线程函数实时检测kill的状态,来return线程。
  19. // 通过等待之后,也要检查kill的状态,如果为真,那么就不能执行功能函数,应该直接return
  20. 注:notify唤醒线程之后,wait里面的判断函数会重新判断。
  21. 最下面有使用样例,
  22. */
  23. #ifndef LIDARMEASURE_THREAD_CONDITION_H
  24. #define LIDARMEASURE_THREAD_CONDITION_H
  25. #include <ratio>
  26. #include <chrono>
  27. #include <thread>
  28. #include <atomic>
  29. #include <mutex>
  30. #include <condition_variable>
  31. #include <functional>
  32. class Thread_condition {
  33. public:
  34. Thread_condition();
  35. Thread_condition(const Thread_condition &other) = delete;
  36. ~Thread_condition();
  37. //无限等待,由 is_pass_wait 决定是否阻塞。
  38. //返回m_pass,
  39. bool wait();
  40. //等待一定的时间(默认时间单位:毫秒ms),由 is_pass_wait 决定是否阻塞。
  41. //return:is_pass_wait的结果, true:线程直接通过等待,false:线程超时了,然后通过等待。
  42. //注意了:线程阻塞期间,是不会return的。
  43. bool wait_for_millisecond(unsigned int millisecond);
  44. //等待一定的时间(时间单位可调),由 is_pass_wait 决定是否阻塞。
  45. //return:is_pass_wait的结果, true:线程直接通过等待,false:线程超时了,然后通过等待。
  46. //注意了:线程阻塞期间,是不会return的。
  47. template<typename _Rep, typename _Period>
  48. bool wait_for_ex(const std::chrono::duration<_Rep, _Period> &time_duration);
  49. //唤醒已经阻塞的线程,唤醒一个线程
  50. //pass_ever 或者 pass_once 为真时,才能唤醒线程。都为假时,线程进入等待。
  51. void notify_one(bool pass_ever, bool pass_once = false);
  52. //唤醒已经阻塞的线程,唤醒全部线程
  53. //pass_ever 或者 pass_once 为真时,才能唤醒线程。都为假时,线程进入等待。
  54. void notify_all(bool pass_ever, bool pass_once = false);
  55. //注:notify_all(false, true)和notify_one(false, true) 一样,只能让其中一个线程执行一次
  56. //杀死所有的线程,强制退出线程函数,只是操作受当前Thread_condition影响的所有线程
  57. //唤醒所有线程,使其通过等待,但是不能运行功能函数,必须直接return
  58. // 注:只是修改m_kill为true,需要线程函数实时检测kill的状态,来return线程。
  59. // 通过等待之后,也要检查kill的状态,如果为真,那么就不能执行功能函数,应该直接return
  60. void kill_all();
  61. //判断是否存活,只有活着才能继续支持子线程从功能函数,否则需要强制退出函数并结束子线程
  62. bool is_alive();
  63. //判断是否等待, 外部线程通过这个函数来查询this线程的工作状态,
  64. bool is_waiting();
  65. //判断是否工作, 外部线程通过这个函数来查询this线程的工作状态,
  66. bool is_working();
  67. public:
  68. bool get_kill_flag();
  69. bool get_pass_ever();
  70. bool get_pass_once();
  71. void set_kill_flag(bool kill);
  72. void set_pass_ever(bool pass_ever);
  73. void set_pass_once(bool pass_once);
  74. void reset(bool kill = false, bool pass_ever = false, bool pass_once = false);
  75. protected:
  76. //判断线程是否可以通过等待,wait系列函数的判断标志
  77. //注:m_kill或者m_pass为真时,return true
  78. static bool is_pass_wait(Thread_condition *other);
  79. std::atomic<bool> m_kill_flag; //是否杀死线程,让线程强制退出,
  80. std::atomic<bool> m_pass_ever; //线程能否直接通过等待,对后面的线程也生效。
  81. std::atomic<bool> m_pass_once; //线程能否直接通过等待,一次(通过一次之后,wait里面自动改为false)
  82. std::atomic<bool> m_working_flag; //线程是否进入工作的标志位, false:表示线程进行进入wait等待, true:表示线程仍然在运行中,
  83. std::mutex m_mutex; //线程的锁
  84. std::condition_variable m_condition_variable; //线程的条件变量
  85. private:
  86. };
  87. //等待一定的时间(时间单位可调),由 is_pass_wait 决定是否阻塞。
  88. //return:is_pass_wait的结果, true:线程直接通过等待,false:线程超时了,然后通过等待。
  89. //注意了:线程阻塞期间,是不会return的。
  90. template<typename _Rep, typename _Period>
  91. bool Thread_condition::wait_for_ex(const std::chrono::duration<_Rep, _Period> &time_duration) {
  92. std::unique_lock<std::mutex> loc(m_mutex);
  93. m_condition_variable.wait_for(loc, std::chrono::duration<_Rep, _Period>(time_duration),
  94. std::bind(is_pass_wait, this));
  95. bool t_pass = is_pass_wait(this);
  96. m_pass_once = false;
  97. return t_pass;
  98. }
  99. #endif //LIDARMEASURE_THREAD_CONDITION_H
  100. /*
  101. //使用样例:
  102. std::thread* mp_thread_receive; //接受缓存的线程指针
  103. Thread_condition m_condition_receive; //接受缓存的条件变量
  104. void thread_receive()
  105. {
  106. while (m_condition_receive.is_alive())
  107. {
  108. m_condition_receive.wait();
  109. if ( m_condition_receive.is_alive() )
  110. {
  111. //do everything
  112. }
  113. }
  114. return;
  115. }
  116. //main函数的主线程
  117. int main(int argc,char* argv[])
  118. {
  119. //线程创建之后, 默认等待
  120. m_condition_receive.reset(false, false, false);
  121. mp_thread_receive = new std::thread(& thread_receive );
  122. //唤醒所有线程, 然后线程可以一直通过wait等待, 线程进入无限制的循环工作.
  123. m_condition_receive.notify_all(true);
  124. //暂停所有线程, 然后线程还是继续工作, 直到下一次循环, 进入wait等待
  125. m_condition_receive.notify_all(false);
  126. //如果线程单次循环运行时间较长, 需要等待线程完全停止, 才能读写公共的内存,
  127. if ( m_condition_receive.is_waiting() )
  128. {
  129. // 读写公共的内存,
  130. }
  131. //唤醒一个线程, 然后线程循环一次, 然后下次循环进入等待
  132. m_condition_receive.notify_all(false, true);
  133. //杀死线程,
  134. m_condition_receive.kill_all();
  135. //在线程join结束之后, 就可以可以回收线程内存资源
  136. mp_thread_receive->join();
  137. delete mp_thread_receive;
  138. mp_thread_receive = NULL;
  139. }
  140. */