Line data Source code
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 6643002 : Callback(Layer & systemLayer, TimerCompleteCallback onComplete, void * appState) :
58 6643002 : mSystemLayer(&systemLayer), mOnComplete(onComplete), mAppState(appState)
59 6643002 : {}
60 11643 : void Invoke() const { mOnComplete(mSystemLayer, mAppState); }
61 7403770 : const TimerCompleteCallback & GetOnComplete() const { return mOnComplete; }
62 6684752 : void * GetAppState() const { return mAppState; }
63 : 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 6643002 : TimerData(Layer & systemLayer, System::Clock::Timestamp awakenTime, TimerCompleteCallback onComplete, void * appState) :
75 6643002 : mAwakenTime(awakenTime), mCallback(systemLayer, onComplete, appState)
76 6643002 : {}
77 : ~TimerData() = default;
78 :
79 : /**
80 : * Return the expiration time.
81 : */
82 25066174 : Clock::Timestamp AwakenTime() const { return mAwakenTime; }
83 :
84 : /**
85 : * Return callback information.
86 : */
87 14100165 : 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 LayerImplSelect;
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 6643002 : Node(Layer & systemLayer, System::Clock::Timestamp awakenTime, TimerCompleteCallback onComplete, void * appState) :
116 6643002 : TimerData(systemLayer, awakenTime, onComplete, appState), mNextTimer(nullptr)
117 6643002 : {}
118 : Node * mNextTimer;
119 : };
120 :
121 0 : 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 6601573 : Node * Earliest() const { return mEarliestTimer; }
165 :
166 : /**
167 : * Test whether there are any timers.
168 : */
169 6601568 : 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 99 : 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 6643002 : Timer * Create(Layer & systemLayer, System::Clock::Timestamp awakenTime, TimerCompleteCallback onComplete, void * appState)
205 : {
206 6643002 : Timer * timer = mTimerPool.CreateObject(systemLayer, awakenTime, onComplete, appState);
207 6643002 : if (timer != nullptr)
208 : {
209 6643002 : SYSTEM_STATS_INCREMENT(Stats::kSystemLayer_NumTimers);
210 : }
211 :
212 6643002 : return timer;
213 : }
214 :
215 : /**
216 : * Release a timer to the pool.
217 : */
218 6642958 : void Release(Timer * timer)
219 : {
220 6642958 : SYSTEM_STATS_DECREMENT(Stats::kSystemLayer_NumTimers);
221 6642958 : mTimerPool.ReleaseObject(timer);
222 6642958 : }
223 :
224 : /**
225 : * Release all timers.
226 : */
227 99 : void ReleaseAll()
228 : {
229 99 : SYSTEM_STATS_RESET(Stats::kSystemLayer_NumTimers);
230 99 : mTimerPool.ReleaseAll();
231 99 : }
232 :
233 : /**
234 : * Release a timer to the pool and invoke its callback.
235 : */
236 11643 : void Invoke(Timer * timer)
237 : {
238 11643 : typename Timer::Callback callback = timer->GetCallback();
239 11643 : Release(timer);
240 11643 : callback.Invoke();
241 11643 : }
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
|