1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 /** 17 * @file condition_variable.h 18 * 19 * @brief Declares the condition variable interfaces in C++. 20 * 21 * @since 10 22 * @version 1.0 23 */ 24 #ifndef FFRT_API_CPP_CONDITION_VARIABLE_H 25 #define FFRT_API_CPP_CONDITION_VARIABLE_H 26 #include <chrono> 27 #include <mutex> 28 #include "mutex.h" 29 #include "c/condition_variable.h" 30 31 namespace ffrt { 32 enum class cv_status { no_timeout, timeout }; 33 34 class condition_variable : public ffrt_cond_t { 35 public: condition_variable()36 condition_variable() 37 { 38 ffrt_cond_init(this, nullptr); 39 } 40 ~condition_variable()41 ~condition_variable() noexcept 42 { 43 ffrt_cond_destroy(this); 44 } 45 46 condition_variable(const condition_variable&) = delete; 47 condition_variable& operator=(const condition_variable&) = delete; 48 49 template <typename Clock, typename Duration, typename Pred> wait_until(std::unique_lock<mutex> & lk,const std::chrono::time_point<Clock,Duration> & tp,Pred && pred)50 bool wait_until( 51 std::unique_lock<mutex>& lk, const std::chrono::time_point<Clock, Duration>& tp, Pred&& pred) noexcept 52 { 53 while (!pred()) { 54 if (wait_until(lk, tp) == cv_status::timeout) { 55 return pred(); 56 } 57 } 58 return true; 59 } 60 61 template <typename Clock, typename Duration> wait_until(std::unique_lock<mutex> & lk,const std::chrono::time_point<Clock,Duration> & tp)62 cv_status wait_until(std::unique_lock<mutex>& lk, const std::chrono::time_point<Clock, Duration>& tp) noexcept 63 { 64 return _wait_for(lk, tp - Clock::now()); 65 } 66 67 template <typename Rep, typename Period> wait_for(std::unique_lock<mutex> & lk,const std::chrono::duration<Rep,Period> & sleep_time)68 cv_status wait_for(std::unique_lock<mutex>& lk, const std::chrono::duration<Rep, Period>& sleep_time) noexcept 69 { 70 return _wait_for(lk, sleep_time); 71 } 72 73 template <typename Rep, typename Period, typename Pred> wait_for(std::unique_lock<mutex> & lk,const std::chrono::duration<Rep,Period> & sleepTime,Pred && pred)74 bool wait_for( 75 std::unique_lock<mutex>& lk, const std::chrono::duration<Rep, Period>& sleepTime, Pred&& pred) noexcept 76 { 77 return wait_until(lk, std::chrono::steady_clock::now() + sleepTime, std::forward<Pred>(pred)); 78 } 79 80 template <typename Pred> wait(std::unique_lock<mutex> & lk,Pred && pred)81 void wait(std::unique_lock<mutex>& lk, Pred&& pred) 82 { 83 while (!pred()) { 84 wait(lk); 85 } 86 } 87 wait(std::unique_lock<mutex> & lk)88 void wait(std::unique_lock<mutex>& lk) 89 { 90 ffrt_cond_wait(this, lk.mutex()); 91 } 92 notify_one()93 void notify_one() noexcept 94 { 95 ffrt_cond_signal(this); 96 } 97 notify_all()98 void notify_all() noexcept 99 { 100 ffrt_cond_broadcast(this); 101 } 102 103 private: 104 template <typename Rep, typename Period> _wait_for(std::unique_lock<mutex> & lk,const std::chrono::duration<Rep,Period> & dur)105 cv_status _wait_for(std::unique_lock<mutex>& lk, const std::chrono::duration<Rep, Period>& dur) noexcept 106 { 107 timespec ts; 108 std::chrono::nanoseconds ns = std::chrono::steady_clock::now().time_since_epoch(); 109 ns += std::chrono::duration_cast<std::chrono::nanoseconds>(dur); 110 ts.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(ns).count(); 111 ns -= std::chrono::seconds(ts.tv_sec); 112 ts.tv_nsec = static_cast<long>(ns.count()); 113 114 auto ret = ffrt_cond_timedwait(this, lk.mutex(), &ts); 115 if (ret == ffrt_success) { 116 return cv_status::no_timeout; 117 } 118 return cv_status::timeout; 119 } 120 }; 121 } // namespace ffrt 122 #endif 123