xref: /aosp_15_r20/external/pigweed/pw_chrono_stl/public/pw_chrono_stl/system_timer_native.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2021 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 <condition_variable>
17 #include <memory>
18 #include <mutex>
19 
20 #include "pw_chrono/system_clock.h"
21 #include "pw_function/function.h"
22 
23 namespace pw::chrono::backend {
24 namespace internal {
25 
26 using ExpiryFn = Function<void(SystemClock::time_point expired_deadline)>;
27 
28 class NoDepsTimedThreadNotification {
29  public:
30   NoDepsTimedThreadNotification() = default;
31   bool try_acquire();
32   bool try_acquire_until(SystemClock::time_point deadline);
33   void notify();
34 
35  private:
36   std::mutex lock_;
37   std::condition_variable cv_;
38   // Guarded by lock_.
39   bool is_set_ = false;
40 };
41 
42 class TimerState {
43  public:
TimerState(ExpiryFn && cb)44   TimerState(ExpiryFn&& cb) : callback_(std::move(cb)) {}
45 
46   NoDepsTimedThreadNotification timer_thread_wakeup_;
47 
48   // The mutex is used both to ensure the public API is threadsafe and to
49   // ensure that only one expiry callback is executed at time.
50   // A recursive mutex is used as the timer callback must be able to invoke
51   // its own public API.
52   std::recursive_mutex lock_;
53 
54   // All guarded by `lock_`;
55   const ExpiryFn callback_;
56   SystemClock::time_point expiry_deadline_;
57   bool enabled_ = false;
58   bool running_ = true;
59 };
60 
61 }  // namespace internal
62 
63 class NativeSystemTimer {
64  public:
65   NativeSystemTimer(internal::ExpiryFn&& callback);
66   void InvokeAt(SystemClock::time_point timestamp);
67   void Cancel();
68   void Kill();
69 
70  private:
71   // Instead of using a more complex blocking timer cleanup, a shared_pointer is
72   // used so that the heap allocation is still valid for the detached threads
73   // even after the NativeSystemTimer has been destructed. Note this is shared
74   // with all detached threads.
75   std::shared_ptr<internal::TimerState> timer_state_;
76 };
77 
78 using NativeSystemTimerHandle = NativeSystemTimer&;
79 
80 }  // namespace pw::chrono::backend
81