1 // Copyright 2022 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://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, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include <mutex> 17 18 #include "pw_chrono/system_clock.h" 19 #include "pw_sync/mutex.h" 20 #include "pw_sync_backend/condition_variable_native.h" 21 22 namespace pw::sync { 23 24 // ConditionVariable represents a condition variable using an API very similar 25 // to std::condition_variable. Implementations of this class should share the 26 // same semantics as std::condition_variable. 27 class ConditionVariable { 28 public: 29 using native_handle_type = backend::NativeConditionVariableHandle; 30 31 ConditionVariable() = default; 32 33 ConditionVariable(const ConditionVariable&) = delete; 34 35 ~ConditionVariable() = default; 36 37 ConditionVariable& operator=(const ConditionVariable&) = delete; 38 39 // Wake up one thread waiting on a condition. 40 // 41 // The thread will re-evaluate the condition via its predicate. Threads where 42 // the predicate evaluates false will go back to waiting. The new order of 43 // waiting threads is undefined. 44 void notify_one(); 45 46 // Wake up all threads waiting on the condition variable. 47 // 48 // Woken threads will re-evaluate the condition via their predicate. Threads 49 // where the predicate evaluates false will go back to waiting. The new order 50 // of waiting threads is undefined. 51 void notify_all(); 52 53 // Block the current thread until predicate() == true. 54 // 55 // Precondition: the provided lock must be locked. 56 template <typename Predicate> 57 void wait(std::unique_lock<Mutex>& lock, Predicate predicate); 58 59 // Block the current thread for a duration up to the given timeout or 60 // until predicate() == true whichever comes first. 61 // 62 // Returns: true if predicate() == true. 63 // false if timeout expired. 64 // 65 // Precondition: the provided lock must be locked. 66 template <typename Predicate> 67 bool wait_for(std::unique_lock<Mutex>& lock, 68 pw::chrono::SystemClock::duration timeout, 69 Predicate predicate); 70 71 // Block the current thread until given point in time or until predicate() == 72 // true whichever comes first. 73 // 74 // Returns: true if predicate() == true. 75 // false if the deadline was reached. 76 // 77 // Precondition: the provided lock must be locked. 78 template <typename Predicate> 79 bool wait_until(std::unique_lock<Mutex>& lock, 80 pw::chrono::SystemClock::time_point deadline, 81 Predicate predicate); 82 83 native_handle_type native_handle(); 84 85 private: 86 backend::NativeConditionVariable native_type_; 87 }; 88 89 } // namespace pw::sync 90 91 #include "pw_sync_backend/condition_variable_inline.h" 92