/src/connectedhomeip/src/system/SystemTimer.h
Line | Count | Source |
1 | | /* |
2 | | * |
3 | | * Copyright (c) 2020 Project CHIP Authors |
4 | | * Copyright (c) 2016-2017 Nest Labs, Inc. |
5 | | * |
6 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | | * you may not use this file except in compliance with the License. |
8 | | * You may obtain a copy of the License at |
9 | | * |
10 | | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | | * |
12 | | * Unless required by applicable law or agreed to in writing, software |
13 | | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | | * See the License for the specific language governing permissions and |
16 | | * limitations under the License. |
17 | | */ |
18 | | |
19 | | /** |
20 | | * This file defines the chip::System::Timer class and related types that can be used for representing |
21 | | * an in-progress one-shot timer. Implementations of System::Layer may (but are not required to) use |
22 | | * these for their versions of timer events. |
23 | | */ |
24 | | |
25 | | #pragma once |
26 | | |
27 | | // Include configuration headers |
28 | | #include <system/SystemConfig.h> |
29 | | |
30 | | // Include dependent headers |
31 | | #include <lib/support/DLLUtil.h> |
32 | | #include <lib/support/Pool.h> |
33 | | |
34 | | #include <system/SystemClock.h> |
35 | | #include <system/SystemError.h> |
36 | | #include <system/SystemLayer.h> |
37 | | #include <system/SystemStats.h> |
38 | | |
39 | | #if CHIP_SYSTEM_CONFIG_USE_DISPATCH |
40 | | #include <dispatch/dispatch.h> |
41 | | #endif |
42 | | |
43 | | namespace chip { |
44 | | namespace System { |
45 | | |
46 | | class Layer; |
47 | | |
48 | | /** |
49 | | * Basic Timer information: time and callback. |
50 | | */ |
51 | | class DLL_EXPORT TimerData |
52 | | { |
53 | | public: |
54 | | class Callback |
55 | | { |
56 | | public: |
57 | | Callback(Layer & systemLayer, TimerCompleteCallback onComplete, void * appState) : |
58 | 30.4k | mSystemLayer(&systemLayer), mOnComplete(onComplete), mAppState(appState) |
59 | 30.4k | {} |
60 | 6.21k | void Invoke() const { mOnComplete(mSystemLayer, mAppState); } |
61 | 130k | const TimerCompleteCallback & GetOnComplete() const { return mOnComplete; } |
62 | 23.4k | void * GetAppState() const { return mAppState; } |
63 | 0 | Layer * GetSystemLayer() const { return mSystemLayer; } |
64 | | |
65 | | private: |
66 | | #if CHIP_SYSTEM_CONFIG_USE_LIBEV |
67 | | friend class LayerImplSelect; |
68 | | #endif |
69 | | Layer * mSystemLayer; |
70 | | TimerCompleteCallback mOnComplete; |
71 | | void * mAppState; |
72 | | }; |
73 | | |
74 | | TimerData(Layer & systemLayer, System::Clock::Timestamp awakenTime, TimerCompleteCallback onComplete, void * appState) : |
75 | 30.4k | mAwakenTime(awakenTime), mCallback(systemLayer, onComplete, appState) |
76 | 30.4k | {} |
77 | | ~TimerData() = default; |
78 | | |
79 | | /** |
80 | | * Return the expiration time. |
81 | | */ |
82 | 147k | Clock::Timestamp AwakenTime() const { return mAwakenTime; } |
83 | | |
84 | | /** |
85 | | * Return callback information. |
86 | | */ |
87 | 160k | const Callback & GetCallback() const { return mCallback; } |
88 | | |
89 | | private: |
90 | | Clock::Timestamp mAwakenTime; |
91 | | Callback mCallback; |
92 | | |
93 | | #if CHIP_SYSTEM_CONFIG_USE_DISPATCH |
94 | | friend class LayerImplDispatch; |
95 | | dispatch_source_t mTimerSource = nullptr; |
96 | | #elif CHIP_SYSTEM_CONFIG_USE_LIBEV |
97 | | friend class LayerImplSelect; |
98 | | struct ev_timer mLibEvTimer; |
99 | | #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH |
100 | | |
101 | | // Not defined |
102 | | TimerData(const TimerData &) = delete; |
103 | | TimerData & operator=(const TimerData &) = delete; |
104 | | }; |
105 | | |
106 | | /** |
107 | | * List of `Timer`s ordered by expiration time. |
108 | | */ |
109 | | class TimerList |
110 | | { |
111 | | public: |
112 | | class Node : public TimerData |
113 | | { |
114 | | public: |
115 | | Node(Layer & systemLayer, System::Clock::Timestamp awakenTime, TimerCompleteCallback onComplete, void * appState) : |
116 | 30.4k | TimerData(systemLayer, awakenTime, onComplete, appState), mNextTimer(nullptr) |
117 | 30.4k | {} |
118 | | Node * mNextTimer; |
119 | | }; |
120 | | |
121 | 7.48k | TimerList() : mEarliestTimer(nullptr) {} |
122 | | |
123 | | /** |
124 | | * Add a timer to the list |
125 | | * |
126 | | * @return The new earliest timer in the list. If this is the newly added timer, that implies it is earlier |
127 | | * than any existing timer. |
128 | | */ |
129 | | Node * Add(Node * timer); |
130 | | |
131 | | /** |
132 | | * Remove the given timer from the list, if present. It is not an error for the timer not to be present. |
133 | | * |
134 | | * @return The new earliest timer in the list, or nullptr if the list is empty. |
135 | | */ |
136 | | Node * Remove(Node * remove); |
137 | | |
138 | | /** |
139 | | * Remove the first timer with the given properties, if present. It is not an error for no such timer to be present. |
140 | | * |
141 | | * @return The removed timer, or nullptr if the list contains no matching timer. |
142 | | */ |
143 | | Node * Remove(TimerCompleteCallback onComplete, void * appState); |
144 | | |
145 | | /** |
146 | | * Remove and return the earliest timer in the list. |
147 | | * |
148 | | * @return The earliest timer, or nullptr if the list is empty. |
149 | | */ |
150 | | Node * PopEarliest(); |
151 | | |
152 | | /** |
153 | | * Remove and return the earliest timer in the list, provided it expires earlier than the given time @a t. |
154 | | * |
155 | | * @return The earliest timer expiring before @a t, or nullptr if there is no such timer. |
156 | | */ |
157 | | Node * PopIfEarlier(Clock::Timestamp t); |
158 | | |
159 | | /** |
160 | | * Get the earliest timer in the list. |
161 | | * |
162 | | * @return The earliest timer, or nullptr if there are no timers. |
163 | | */ |
164 | 7.43k | Node * Earliest() const { return mEarliestTimer; } |
165 | | |
166 | | /** |
167 | | * Test whether there are any timers. |
168 | | */ |
169 | 7.43k | bool Empty() const { return mEarliestTimer == nullptr; } |
170 | | |
171 | | /** |
172 | | * Remove and return all timers that expire before the given time @a t. |
173 | | */ |
174 | | TimerList ExtractEarlier(Clock::Timestamp t); |
175 | | |
176 | | /** |
177 | | * Remove all timers. |
178 | | */ |
179 | 2.81k | void Clear() { mEarliestTimer = nullptr; } |
180 | | |
181 | | /** |
182 | | * Find the timer with the given properties, if present, and return its remaining time |
183 | | * |
184 | | * @return The remaining time on this partifcular timer or 0 if not found. |
185 | | */ |
186 | | Clock::Timeout GetRemainingTime(TimerCompleteCallback aOnComplete, void * aAppState); |
187 | | |
188 | | private: |
189 | | Node * mEarliestTimer; |
190 | | }; |
191 | | |
192 | | /** |
193 | | * ObjectPool wrapper that keeps System Timer statistics. |
194 | | */ |
195 | | template <typename T = TimerList::Node> |
196 | | class TimerPool |
197 | | { |
198 | | public: |
199 | | using Timer = T; |
200 | | |
201 | | /** |
202 | | * Create a new timer from the pool. |
203 | | */ |
204 | | Timer * Create(Layer & systemLayer, System::Clock::Timestamp awakenTime, TimerCompleteCallback onComplete, void * appState) |
205 | 30.4k | { |
206 | 30.4k | Timer * timer = mTimerPool.CreateObject(systemLayer, awakenTime, onComplete, appState); |
207 | 30.4k | if (timer != nullptr) |
208 | 30.4k | { |
209 | 30.4k | SYSTEM_STATS_INCREMENT(Stats::kSystemLayer_NumTimers); |
210 | 30.4k | } |
211 | | |
212 | 30.4k | return timer; |
213 | 30.4k | } |
214 | | |
215 | | /** |
216 | | * Release a timer to the pool. |
217 | | */ |
218 | | void Release(Timer * timer) |
219 | 28.1k | { |
220 | 28.1k | SYSTEM_STATS_DECREMENT(Stats::kSystemLayer_NumTimers); |
221 | 28.1k | mTimerPool.ReleaseObject(timer); |
222 | 28.1k | } |
223 | | |
224 | | /** |
225 | | * Release all timers. |
226 | | */ |
227 | | void ReleaseAll() |
228 | 2.81k | { |
229 | 2.81k | SYSTEM_STATS_RESET(Stats::kSystemLayer_NumTimers); |
230 | 2.81k | mTimerPool.ReleaseAll(); |
231 | 2.81k | } |
232 | | |
233 | | /** |
234 | | * Release a timer to the pool and invoke its callback. |
235 | | */ |
236 | | void Invoke(Timer * timer) |
237 | 6.21k | { |
238 | 6.21k | typename Timer::Callback callback = timer->GetCallback(); |
239 | 6.21k | Release(timer); |
240 | 6.21k | callback.Invoke(); |
241 | 6.21k | } |
242 | | |
243 | | private: |
244 | | friend class TestSystemTimer_CheckTimerPool_Test; |
245 | | ObjectPool<Timer, CHIP_SYSTEM_CONFIG_NUM_TIMERS> mTimerPool; |
246 | | }; |
247 | | |
248 | | } // namespace System |
249 | | } // namespace chip |