xref: /aosp_15_r20/external/pigweed/pw_sync/public/pw_sync/condition_variable.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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 // IMPORTANT: DO NOT USE!
17 //
18 // The interface defined below is currently ONLY implemented by the pw_sync_stl
19 // backed, and cannot be implemented efficiently by other backends.
20 // Specifically, it is difficult for condition variables notifying waiters
21 // efficiently:
22 //
23 // - If wake condition(s) are checked by the waiting threads, these threads must
24 //   first be awoken to check the condition, and resume sleeping if it is not
25 //   met. These spurious wakeups consume time and power.
26 // - If wake condition(s) are checked by the notifier, synchronization is
27 //   required. This prevents the condition variable from being used in ISRs.
28 //   Moreover, at least some
29 //
30 // As a result, the interface below WILL either change or be removed. Do not
31 // depend on it.
32 //
33 // TODO(b/294395229): Revisit the interface.
34 
35 #include <mutex>
36 
37 #include "pw_chrono/system_clock.h"
38 #include "pw_sync/mutex.h"
39 #include "pw_sync_backend/condition_variable_native.h"
40 
41 namespace pw::sync {
42 
43 // ConditionVariable represents a condition variable using an API very similar
44 // to std::condition_variable. Implementations of this class should share the
45 // same semantics as std::condition_variable.
46 class ConditionVariable {
47  public:
48   using native_handle_type = backend::NativeConditionVariableHandle;
49 
50   ConditionVariable() = default;
51 
52   ConditionVariable(const ConditionVariable&) = delete;
53 
54   ~ConditionVariable() = default;
55 
56   ConditionVariable& operator=(const ConditionVariable&) = delete;
57 
58   // Wake up one thread waiting on a condition.
59   //
60   // The thread will re-evaluate the condition via its predicate. Threads where
61   // the predicate evaluates false will go back to waiting. The new order of
62   // waiting threads is undefined.
63   void notify_one();
64 
65   // Wake up all threads waiting on the condition variable.
66   //
67   // Woken threads will re-evaluate the condition via their predicate. Threads
68   // where the predicate evaluates false will go back to waiting. The new order
69   // of waiting threads is undefined.
70   void notify_all();
71 
72   // Block the current thread until predicate() == true.
73   //
74   // Precondition: the provided lock must be locked.
75   template <typename Predicate>
76   void wait(std::unique_lock<Mutex>& lock, Predicate predicate);
77 
78   // Block the current thread for a duration up to the given timeout or
79   // until predicate() == true whichever comes first.
80   //
81   // Returns: true if predicate() == true.
82   //          false if timeout expired.
83   //
84   // Precondition: the provided lock must be locked.
85   template <typename Predicate>
86   bool wait_for(std::unique_lock<Mutex>& lock,
87                 pw::chrono::SystemClock::duration timeout,
88                 Predicate predicate);
89 
90   // Block the current thread until given point in time or until predicate() ==
91   // true whichever comes first.
92   //
93   // Returns: true if predicate() == true.
94   //          false if the deadline was reached.
95   //
96   // Precondition: the provided lock must be locked.
97   template <typename Predicate>
98   bool wait_until(std::unique_lock<Mutex>& lock,
99                   pw::chrono::SystemClock::time_point deadline,
100                   Predicate predicate);
101 
102   native_handle_type native_handle();
103 
104  private:
105   backend::NativeConditionVariable native_type_;
106 };
107 
108 }  // namespace pw::sync
109 
110 #include "pw_sync_backend/condition_variable_inline.h"
111