• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <semaphore.h>
20 #include <chrono>
21 #include <condition_variable>
22 #include <thread>
23 #include "../Clock.h"
24 
25 #include <android-base/thread_annotations.h>
26 
27 namespace android {
28 namespace scheduler {
29 
30 /*
31  * Class that sets off a timer for a given interval, and fires a callback when the
32  * interval expires.
33  */
34 class OneShotTimer {
35 public:
36     using Interval = std::chrono::milliseconds;
37     using ResetCallback = std::function<void()>;
38     using TimeoutCallback = std::function<void()>;
39 
40     OneShotTimer(std::string name, const Interval& interval, const ResetCallback& resetCallback,
41                  const TimeoutCallback& timeoutCallback,
42                  std::unique_ptr<Clock> clock = std::make_unique<SteadyClock>());
43     ~OneShotTimer();
44 
45     // Initializes and turns on the idle timer.
46     void start();
47     // Stops the idle timer and any held resources.
48     void stop();
49     // Resets the wakeup time and fires the reset callback.
50     void reset();
51 
52     std::string dump() const;
53 
54 private:
55     // Enum to track in what state is the timer.
56     enum class TimerState {
57         // The internal timer thread has been destroyed, and no state is
58         // tracked.
59         // Possible state transitions: RESET
60         STOPPED = 0,
61         // An external thread has just reset this timer.
62         // If there is a reset callback, then that callback is fired.
63         // Possible state transitions: STOPPED, WAITING
64         RESET = 1,
65         // This timer is waiting for the timeout interval to expire.
66         // Possible state transaitions: STOPPED, RESET, IDLE
67         WAITING = 2,
68         // The timeout interval has expired, so we are sleeping now.
69         // Possible state transaitions: STOPPED, RESET
70         IDLE = 3
71     };
72 
73     // Function that loops until the condition for stopping is met.
74     void loop();
75 
76     // Checks whether mResetTriggered and mStopTriggered were set and updates
77     // mState if so.
78     TimerState checkForResetAndStop(TimerState state);
79 
80     // Thread waiting for timer to expire.
81     std::thread mThread;
82 
83     // Clock object for the timer. Mocked in unit tests.
84     std::unique_ptr<Clock> mClock;
85 
86     // Semaphore to keep mThread synchronized.
87     sem_t mSemaphore;
88 
89     // Timer's name.
90     std::string mName;
91 
92     // Interval after which timer expires.
93     const Interval mInterval;
94 
95     // Callback that happens when timer resets.
96     const ResetCallback mResetCallback;
97 
98     // Callback that happens when timer expires.
99     const TimeoutCallback mTimeoutCallback;
100 
101     // After removing lock guarding mState, the state can be now accessed at
102     // any time. Keep a bool if the reset or stop were requested, and occasionally
103     // check in the main loop if they were.
104     std::atomic<bool> mResetTriggered = false;
105     std::atomic<bool> mStopTriggered = false;
106     std::atomic<bool> mWaiting = false;
107     std::atomic<std::chrono::steady_clock::time_point> mLastResetTime;
108 };
109 
110 } // namespace scheduler
111 } // namespace android
112