• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_RecurrentTimer_H_
18 #define android_hardware_automotive_vehicle_aidl_impl_vhal_include_RecurrentTimer_H_
19 
20 #include <android-base/thread_annotations.h>
21 
22 #include <memory>
23 #include <mutex>
24 #include <queue>
25 #include <thread>
26 #include <unordered_map>
27 #include <vector>
28 
29 namespace android {
30 namespace hardware {
31 namespace automotive {
32 namespace vehicle {
33 
34 // A thread-safe recurrent timer.
35 class RecurrentTimer final {
36   public:
37     // The class for the function that would be called recurrently.
38     using Callback = std::function<void()>;
39 
40     RecurrentTimer();
41 
42     ~RecurrentTimer();
43 
44     // Registers a recurrent callback for a given interval.
45     // Registering the same callback twice will override the interval provided before.
46     void registerTimerCallback(int64_t intervalInNano, std::shared_ptr<Callback> callback);
47 
48     // Unregisters a previously registered recurrent callback.
49     void unregisterTimerCallback(std::shared_ptr<Callback> callback);
50 
51   private:
52     // friend class for unit testing.
53     friend class RecurrentTimerTest;
54 
55     struct CallbackInfo {
56         std::shared_ptr<Callback> callback;
57         int64_t interval;
58         int64_t nextTime;
59         // A flag to indicate whether this CallbackInfo is already outdated and should be ignored.
60         // The reason we need this flag is because we cannot easily remove an element from a heap.
61         bool outdated = false;
62 
63         static bool cmp(const std::unique_ptr<CallbackInfo>& lhs,
64                         const std::unique_ptr<CallbackInfo>& rhs);
65     };
66 
67     std::mutex mLock;
68     std::thread mThread;
69     std::condition_variable mCond;
70     bool mStopRequested GUARDED_BY(mLock) = false;
71     // A map to map each callback to its current active CallbackInfo in the mCallbackQueue.
72     std::unordered_map<std::shared_ptr<Callback>, CallbackInfo*> mCallbacks GUARDED_BY(mLock);
73     // A min-heap sorted by nextTime. Note that because we cannot remove arbitrary element from the
74     // heap, a single Callback can have multiple entries in this queue, all but one should be valid.
75     // The rest should be mark as outdated. The valid one is one stored in mCallbacks.
76     std::vector<std::unique_ptr<CallbackInfo>> mCallbackQueue GUARDED_BY(mLock);
77 
78     void loop();
79 
80     // Mark the callbackInfo as outdated and should be ignored when popped from the heap.
81     void markOutdatedLocked(CallbackInfo* callback) REQUIRES(mLock);
82     // Remove all outdated callbackInfos from the top of the heap. This function must be called
83     // each time we might introduce outdated elements to the top. We must make sure the heap is
84     // always valid from the top.
85     void removeInvalidCallbackLocked() REQUIRES(mLock);
86     // Gets the next calblack to run (must be valid) from the heap, update its nextTime and put
87     // it back to the heap.
88     std::shared_ptr<Callback> getNextCallbackLocked(int64_t now) REQUIRES(mLock);
89 };
90 
91 }  // namespace vehicle
92 }  // namespace automotive
93 }  // namespace hardware
94 }  // namespace android
95 
96 #endif  // android_hardware_automotive_vehicle_aidl_impl_vhal_include_RecurrentTimer_H_
97