xref: /aosp_15_r20/external/federated-compute/fcp/base/clock.h (revision 14675a029014e728ec732f129a32e299b2da0601)
1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker  * Copyright 2020 Google LLC
3*14675a02SAndroid Build Coastguard Worker  *
4*14675a02SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*14675a02SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*14675a02SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*14675a02SAndroid Build Coastguard Worker  *
8*14675a02SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*14675a02SAndroid Build Coastguard Worker  *
10*14675a02SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*14675a02SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*14675a02SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*14675a02SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*14675a02SAndroid Build Coastguard Worker  * limitations under the License.
15*14675a02SAndroid Build Coastguard Worker  */
16*14675a02SAndroid Build Coastguard Worker 
17*14675a02SAndroid Build Coastguard Worker #ifndef FCP_BASE_CLOCK_H_
18*14675a02SAndroid Build Coastguard Worker #define FCP_BASE_CLOCK_H_
19*14675a02SAndroid Build Coastguard Worker 
20*14675a02SAndroid Build Coastguard Worker #include <map>
21*14675a02SAndroid Build Coastguard Worker #include <memory>
22*14675a02SAndroid Build Coastguard Worker #include <optional>
23*14675a02SAndroid Build Coastguard Worker #include <vector>
24*14675a02SAndroid Build Coastguard Worker 
25*14675a02SAndroid Build Coastguard Worker #include "absl/synchronization/mutex.h"
26*14675a02SAndroid Build Coastguard Worker #include "absl/time/time.h"
27*14675a02SAndroid Build Coastguard Worker 
28*14675a02SAndroid Build Coastguard Worker namespace fcp {
29*14675a02SAndroid Build Coastguard Worker 
30*14675a02SAndroid Build Coastguard Worker /*
31*14675a02SAndroid Build Coastguard Worker  * Clock is an abstract class representing a Clock, which is an object that can
32*14675a02SAndroid Build Coastguard Worker  * tell you the current time and schedule a wakeable event in a future.
33*14675a02SAndroid Build Coastguard Worker  */
34*14675a02SAndroid Build Coastguard Worker class Clock {
35*14675a02SAndroid Build Coastguard Worker  public:
36*14675a02SAndroid Build Coastguard Worker   // Returns a pointer to the global realtime clock. The caller does not
37*14675a02SAndroid Build Coastguard Worker   // own the returned pointer and should not delete it. The returned clock
38*14675a02SAndroid Build Coastguard Worker   // is thread-safe.
39*14675a02SAndroid Build Coastguard Worker   static Clock* RealClock();
40*14675a02SAndroid Build Coastguard Worker 
41*14675a02SAndroid Build Coastguard Worker   virtual ~Clock() = default;
42*14675a02SAndroid Build Coastguard Worker 
43*14675a02SAndroid Build Coastguard Worker   // Returns current time.
44*14675a02SAndroid Build Coastguard Worker   virtual absl::Time Now() = 0;
45*14675a02SAndroid Build Coastguard Worker 
46*14675a02SAndroid Build Coastguard Worker   // Sleeps for the specified duration.
47*14675a02SAndroid Build Coastguard Worker   virtual void Sleep(absl::Duration d) = 0;
48*14675a02SAndroid Build Coastguard Worker 
49*14675a02SAndroid Build Coastguard Worker   // An abstract interface for a waiter class that is passed to
50*14675a02SAndroid Build Coastguard Worker   // WakeupWithDeadline and is responsible for handling a timer wake-up.
51*14675a02SAndroid Build Coastguard Worker   // Waiter interface doesn't support a cancellation mechanism which means
52*14675a02SAndroid Build Coastguard Worker   //
53*14675a02SAndroid Build Coastguard Worker   // Note: it is up to Waiter implementation how to handle a cancellation. Clock
54*14675a02SAndroid Build Coastguard Worker   // itself doesn't manage cancellation and will call WakeUp() on all all alarms
55*14675a02SAndroid Build Coastguard Worker   // once their deadline time is past due.
56*14675a02SAndroid Build Coastguard Worker   class Waiter {
57*14675a02SAndroid Build Coastguard Worker    public:
58*14675a02SAndroid Build Coastguard Worker     virtual ~Waiter() = default;
59*14675a02SAndroid Build Coastguard Worker     // A callback method that is called when the corresponding deadline is
60*14675a02SAndroid Build Coastguard Worker     // reached. This method may be called on an arbitrary thread.
61*14675a02SAndroid Build Coastguard Worker     virtual void WakeUp() = 0;
62*14675a02SAndroid Build Coastguard Worker   };
63*14675a02SAndroid Build Coastguard Worker 
64*14675a02SAndroid Build Coastguard Worker   // Schedule the waiter to be waked up at the specified deadline.
65*14675a02SAndroid Build Coastguard Worker   void WakeupWithDeadline(absl::Time deadline,
66*14675a02SAndroid Build Coastguard Worker                           const std::shared_ptr<Waiter>& waiter);
67*14675a02SAndroid Build Coastguard Worker 
68*14675a02SAndroid Build Coastguard Worker  protected:
69*14675a02SAndroid Build Coastguard Worker   // Accessors shared for derived clases.
mutex()70*14675a02SAndroid Build Coastguard Worker   absl::Mutex* mutex() { return &mu_; }
71*14675a02SAndroid Build Coastguard Worker 
72*14675a02SAndroid Build Coastguard Worker   // Internal version of now which is called under mutex.
73*14675a02SAndroid Build Coastguard Worker   virtual absl::Time NowLocked()
74*14675a02SAndroid Build Coastguard Worker       ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex()) = 0;
75*14675a02SAndroid Build Coastguard Worker 
76*14675a02SAndroid Build Coastguard Worker   // Overloaded by derived class to implement the actual scheduling.
77*14675a02SAndroid Build Coastguard Worker   virtual void ScheduleWakeup(absl::Time wakeup_time)
78*14675a02SAndroid Build Coastguard Worker       ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex()) = 0;
79*14675a02SAndroid Build Coastguard Worker 
80*14675a02SAndroid Build Coastguard Worker   // Called to dispatch wakeup to all due waiters.
81*14675a02SAndroid Build Coastguard Worker   void DispatchWakeups();
82*14675a02SAndroid Build Coastguard Worker 
83*14675a02SAndroid Build Coastguard Worker  private:
84*14675a02SAndroid Build Coastguard Worker   using WaiterList = std::vector<std::shared_ptr<Waiter>>;
85*14675a02SAndroid Build Coastguard Worker   using WaiterMap = std::map<absl::Time, WaiterList>;
86*14675a02SAndroid Build Coastguard Worker 
87*14675a02SAndroid Build Coastguard Worker   bool CheckReentrancy();
88*14675a02SAndroid Build Coastguard Worker   WaiterList GetExpiredWaiters();
89*14675a02SAndroid Build Coastguard Worker   bool FinishDispatchAndScheduleNextWakeup();
90*14675a02SAndroid Build Coastguard Worker 
91*14675a02SAndroid Build Coastguard Worker   // Mutex that protects the internal state.
92*14675a02SAndroid Build Coastguard Worker   absl::Mutex mu_;
93*14675a02SAndroid Build Coastguard Worker   // Pending (unexpired) waiters ordered by deadline - soonest to latest.
94*14675a02SAndroid Build Coastguard Worker   // Waiters with exactly the same deadline are stored in the same bucket and
95*14675a02SAndroid Build Coastguard Worker   // the order at which they were added is preserved.
96*14675a02SAndroid Build Coastguard Worker   WaiterMap pending_waiters_ ABSL_GUARDED_BY(mutex());
97*14675a02SAndroid Build Coastguard Worker   // This value =0 when no DispatchWakeups() is running;
98*14675a02SAndroid Build Coastguard Worker   //            =1 when DispatchWakeups() is running
99*14675a02SAndroid Build Coastguard Worker   //            >1 when at least one additional DispatchWakeups() call happened
100*14675a02SAndroid Build Coastguard Worker   //               while DispatchWakeups() was running, for example from
101*14675a02SAndroid Build Coastguard Worker   //               a timer elapsing and triggering a wake-up.
102*14675a02SAndroid Build Coastguard Worker   int dispatch_level_ ABSL_GUARDED_BY(mutex()) = 0;
103*14675a02SAndroid Build Coastguard Worker };
104*14675a02SAndroid Build Coastguard Worker 
105*14675a02SAndroid Build Coastguard Worker }  // namespace fcp
106*14675a02SAndroid Build Coastguard Worker 
107*14675a02SAndroid Build Coastguard Worker #endif  // FCP_BASE_CLOCK_H_
108