#include <condition_variable>#include <iostream>#include <mutex>#include <string>#include <thread>std::mutex m;std::condition_variable cv;std::string data;bool ready = false;bool processed = false;void worker_thread(){ // Wait until main() sends data std::unique_lock lk(m); cv.wait(lk, []{ return ready; }); // after the wait, we own the lock. std::cout << "Worker thread is processing data\n"; data += " after processing"; // Send data back to main() processed = true; std::cout << "Worker thread signals data processing completed\n"; // Manual unlocking is done before notifying, to avoid waking up // the waiting thread only to block again (see notify_one for details) lk.unlock(); cv.notify_one();}int main(){ std::thread worker(worker_thread); data = "Example data"; // send data to the worker thread { std::lock_guard lk(m); ready = true; std::cout << "main() signals data ready for processing\n"; } cv.notify_one(); // wait for the worker { std::unique_lock lk(m); cv.wait(lk, []{ return processed; }); } std::cout << "Back in main(), data = " << data << '\n'; worker.join();}
conditional_wait_for_int _cv_started{};// run all theadsstd::async(std::launch::async, []{ _cv_started.set(); // ok, here all threads are alive.});// and wait for all of them are alive_cv_started.wait();
那么,conditional_wait 的实现代码如下:
// conditional_wait, ...namespace hicc::pool { /** * @brief a wrapper class for using std condition variable concisely * @tparam T any type holder * @tparam Pred a functor with prototype `bool()` * @tparam Setter a functor with prototype `void()` * @see hicc::pool::conditional_wait_for_bool * @see hicc::pool::conditional_wait_for_int */ template<typename T, typename Pred = std::function<bool()>, typename Setter = std::function<void()>> class conditional_wait { Pred _p{}; Setter _s{}; protected: std::condition_variable _cv{}; std::mutex _m{}; T _var{}; public: explicit conditional_wait(Pred &&p_, Setter &&s_) : _p(std::move(p_)) , _s(std::move(s_)) {} virtual ~conditional_wait() { clear(); } // conditional_wait(conditional_wait &&) = delete; // conditional_wait &operator=(conditional_wait &&) = delete; CLAZZ_NON_COPYABLE(conditional_wait); public: /** * @brief wait for Pred condition matched */ void wait() { std::unique_lock<std::mutex> lk(_m); _cv.wait(lk, _p); } const bool ConditionMatched = true; /** * @brief wait for Pred condition matched, or a timeout arrived. * @tparam R _Rep * @tparam P _Period * @param rel_time a timeout (std::chrono::duration) * @return true if condition matched, false while not matched. * >> false if the predicate pred still evaluates to false after * the rel_time timeout expired, otherwise true. * * @details blocks the current thread until the condition * variable is woken up or after the specified timeout duration. */ template<class R, class P> bool wait_for(std::chrono::duration<R, P> const &rel_time) { std::unique_lock<std::mutex> lk(_m); return _cv.wait_for(lk, rel_time, _p); } bool wait_for() { return wait_for(std::chrono::hours::max()); } /** * @brief wait_until causes the current thread to block until the * condition variable is notified, a specific time is reached, * or a spurious wakeup occurs, optionally looping until some * predicate is satisfied. * @tparam C Clock * @tparam D Duration * @param timeout_time * @return false if the predicate pred still evaluates to false * after the timeout_time timeout expired, otherwise true. If * the timeout had already expired, evaluates and returns the * result of pred. */ template<class C, class D> bool wait_until(std::chrono::time_point<C, D> const &timeout_time) { std::unique_lock<std::mutex> lk(_m); return _cv.wait_until(lk, timeout_time, _p); } bool wait_until() { return wait_until(std::chrono::time_point<std::chrono::system_clock>::max()); } /** * @brief do Setter, and trigger any one of the wating routines */ void set() { // dbg_debug("%s", __FUNCTION_NAME__); { std::unique_lock<std::mutex> lk(_m); _s(); } _cv.notify_one(); } /** * @brief do Setter, trigger and wake up all waiting routines */ void set_for_all() { // dbg_debug("%s", __FUNCTION_NAME__); { std::unique_lock<std::mutex> lk(_m); _s(); } _cv.notify_all(); } void clear() { _release(); } T const &val() const { return _value(); } T &val() { return _value(); } protected: virtual T const &_value() const { return _var; } virtual T &_value() { return _var; } virtual void _release() {} }; template<typename CW> class cw_setter { public: cw_setter(CW &cw) : _cw(cw) {} ~cw_setter() { _cw.set(); } private: CW &_cw; }; class conditional_wait_for_bool : public conditional_wait<bool> { public: conditional_wait_for_bool() : conditional_wait([this]() { return _wait(); }, [this]() { _set(); }) {} virtual ~conditional_wait_for_bool() = default; conditional_wait_for_bool(conditional_wait_for_bool &&) = delete; conditional_wait_for_bool &operator=(conditional_wait_for_bool &&) = delete; protected: bool _wait() const { return _var; } void _set() { _var = true; } public: void kill() { set_for_all(); } }; class conditional_wait_for_int : public conditional_wait<int> { public: conditional_wait_for_int(int max_value_ = 1) : conditional_wait([this]() { return _wait(); }, [this]() { _set(); }) , _max_value(max_value_) {} virtual ~conditional_wait_for_int() = default; conditional_wait_for_int(conditional_wait_for_int &&) = delete; conditional_wait_for_int &operator=(conditional_wait_for_int &&) = delete; inline int max_val() const { return _max_value; } protected: inline bool _wait() const { return _var >= _max_value; } inline void _set() { _var++; } private: int _max_value; };}