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