/* Thread_condition 是多线程的条件控制类,主要是控制线程的启停和退出 * 线程创建后,一般是循环运行, * 为了防止线程暂满整个cpu,那么需要线程在不工作的是否进入等待状态。 * Thread_condition 就可以控制线程的运行状态。 * std::atomic m_pass_ever //线程能否直接通过等待,对后面的线程也生效。 std::atomic m_pass_once //线程能否直接通过等待,一次(通过一次之后,wait里面自动改为false) * 外部调用notify系列的函数,唤醒等待的线程,让线程执行功能函数。 * 如果需要线程循环多次执行功能函数,那么就使用 notify_all(true),后面的线程可以直接通过等待了。 * 再使用 notify_all(false) ,即可停止线程,让其继续等待。 * 如果只想要线程执行一次,那就使用 notify_all(false, true) * 注:notify_all(false, true)和notify_one(false, true) 一样,只能让其中一个线程执行一次 * * m_kill_flag //是否杀死线程,让线程强制退出, * 外部调用 kill_all() 函数,可以直接通知线程自动退出。 //杀死所有的线程,强制退出线程函数,只是操作受当前Thread_condition影响的所有线程 //唤醒所有线程,使其通过等待,但是不能运行功能函数,必须直接return // 注:只是修改m_kill为true,需要线程函数实时检测kill的状态,来return线程。 // 通过等待之后,也要检查kill的状态,如果为真,那么就不能执行功能函数,应该直接return 注:notify唤醒线程之后,wait里面的判断函数会重新判断。 最下面有使用样例, */ #ifndef LIDARMEASURE_THREAD_CONDITION_H #define LIDARMEASURE_THREAD_CONDITION_H #include #include #include #include #include #include #include class Thread_condition { public: Thread_condition(); Thread_condition(const Thread_condition& other) = delete; ~Thread_condition(); //无限等待,由 is_pass_wait 决定是否阻塞。 //返回m_pass, bool wait(); //等待一定的时间(默认时间单位:毫秒ms),由 is_pass_wait 决定是否阻塞。 //return:is_pass_wait的结果, true:线程直接通过等待,false:线程超时了,然后通过等待。 //注意了:线程阻塞期间,是不会return的。 bool wait_for_millisecond(unsigned int millisecond); //等待一定的时间(时间单位可调),由 is_pass_wait 决定是否阻塞。 //return:is_pass_wait的结果, true:线程直接通过等待,false:线程超时了,然后通过等待。 //注意了:线程阻塞期间,是不会return的。 template bool wait_for_ex(const std::chrono::duration<_Rep, _Period>& time_duration); //唤醒已经阻塞的线程,唤醒一个线程 //pass_ever 或者 pass_once 为真时,才能唤醒线程。都为假时,线程进入等待。 void notify_one(bool pass_ever, bool pass_once = false); //唤醒已经阻塞的线程,唤醒全部线程 //pass_ever 或者 pass_once 为真时,才能唤醒线程。都为假时,线程进入等待。 void notify_all(bool pass_ever, bool pass_once = false); //注:notify_all(false, true)和notify_one(false, true) 一样,只能让其中一个线程执行一次 //杀死所有的线程,强制退出线程函数,只是操作受当前Thread_condition影响的所有线程 //唤醒所有线程,使其通过等待,但是不能运行功能函数,必须直接return // 注:只是修改m_kill为true,需要线程函数实时检测kill的状态,来return线程。 // 通过等待之后,也要检查kill的状态,如果为真,那么就不能执行功能函数,应该直接return void kill_all(); //判断是否存活,只有活着才能继续支持子线程从功能函数,否则需要强制退出函数并结束子线程 bool is_alive(); //判断是否等待, 外部线程通过这个函数来查询this线程的工作状态, bool is_waiting(); //判断是否工作, 外部线程通过这个函数来查询this线程的工作状态, bool is_working(); public: bool get_kill_flag(); bool get_pass_ever(); bool get_pass_once(); void set_kill_flag(bool kill); void set_pass_ever(bool pass_ever); void set_pass_once(bool pass_once); void reset(bool kill = false, bool pass_ever = false, bool pass_once = false); protected: //判断线程是否可以通过等待,wait系列函数的判断标志 //注:m_kill或者m_pass为真时,return true static bool is_pass_wait(Thread_condition * other); std::atomic m_kill_flag; //是否杀死线程,让线程强制退出, std::atomic m_pass_ever; //线程能否直接通过等待,对后面的线程也生效。 std::atomic m_pass_once; //线程能否直接通过等待,一次(通过一次之后,wait里面自动改为false) std::atomic m_working_flag; //线程是否进入工作的标志位, false:表示线程进行进入wait等待, true:表示线程仍然在运行中, std::mutex m_mutex; //线程的锁 std::condition_variable m_condition_variable; //线程的条件变量 private: }; //等待一定的时间(时间单位可调),由 is_pass_wait 决定是否阻塞。 //return:is_pass_wait的结果, true:线程直接通过等待,false:线程超时了,然后通过等待。 //注意了:线程阻塞期间,是不会return的。 template bool Thread_condition::wait_for_ex(const std::chrono::duration<_Rep, _Period>& time_duration) { std::unique_lock loc(m_mutex); m_condition_variable.wait_for(loc, std::chrono::duration<_Rep, _Period>(time_duration), std::bind(is_pass_wait, this)); bool t_pass = is_pass_wait(this); m_pass_once = false; return t_pass; } #endif //LIDARMEASURE_THREAD_CONDITION_H /* //使用样例: std::thread* mp_thread_receive; //接受缓存的线程指针 Thread_condition m_condition_receive; //接受缓存的条件变量 void thread_receive() { while (m_condition_receive.is_alive()) { m_condition_receive.wait(); if ( m_condition_receive.is_alive() ) { //do everything } } return; } //main函数的主线程 int main(int argc,char* argv[]) { //线程创建之后, 默认等待 m_condition_receive.reset(false, false, false); mp_thread_receive = new std::thread(& thread_receive ); //唤醒所有线程, 然后线程可以一直通过wait等待, 线程进入无限制的循环工作. m_condition_receive.notify_all(true); //暂停所有线程, 然后线程还是继续工作, 直到下一次循环, 进入wait等待 m_condition_receive.notify_all(false); //如果线程单次循环运行时间较长, 需要等待线程完全停止, 才能读写公共的内存, if ( m_condition_receive.is_waiting() ) { // 读写公共的内存, } //唤醒一个线程, 然后线程循环一次, 然后下次循环进入等待 m_condition_receive.notify_all(false, true); //杀死线程, m_condition_receive.kill_all(); //在线程join结束之后, 就可以可以回收线程内存资源 mp_thread_receive->join(); delete mp_thread_receive; mp_thread_receive = NULL; } */