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 : class TestTimer;
48 :
49 : /**
50 : * Basic Timer information: time and callback.
51 : */
52 : class DLL_EXPORT TimerData
53 : {
54 : public:
55 : class Callback
56 : {
57 : public:
58 4133046 : Callback(Layer & systemLayer, TimerCompleteCallback onComplete, void * appState) :
59 4133046 : mSystemLayer(&systemLayer), mOnComplete(onComplete), mAppState(appState)
60 4133046 : {}
61 11339 : void Invoke() const { mOnComplete(mSystemLayer, mAppState); }
62 4877185 : const TimerCompleteCallback & GetOnComplete() const { return mOnComplete; }
63 4175094 : void * GetAppState() const { return mAppState; }
64 : Layer * GetSystemLayer() const { return mSystemLayer; }
65 :
66 : private:
67 : #if CHIP_SYSTEM_CONFIG_USE_LIBEV
68 : friend class LayerImplSelect;
69 : #endif
70 : Layer * mSystemLayer;
71 : TimerCompleteCallback mOnComplete;
72 : void * mAppState;
73 : };
74 :
75 4133046 : TimerData(Layer & systemLayer, System::Clock::Timestamp awakenTime, TimerCompleteCallback onComplete, void * appState) :
76 4133046 : mAwakenTime(awakenTime), mCallback(systemLayer, onComplete, appState)
77 4133046 : {}
78 : ~TimerData() = default;
79 :
80 : /**
81 : * Return the expiration time.
82 : */
83 19158933 : Clock::Timestamp AwakenTime() const { return mAwakenTime; }
84 :
85 : /**
86 : * Return callback information.
87 : */
88 9063618 : const Callback & GetCallback() const { return mCallback; }
89 :
90 : private:
91 : Clock::Timestamp mAwakenTime;
92 : Callback mCallback;
93 :
94 : #if CHIP_SYSTEM_CONFIG_USE_DISPATCH
95 : friend class LayerImplSelect;
96 : dispatch_source_t mTimerSource = nullptr;
97 : #elif CHIP_SYSTEM_CONFIG_USE_LIBEV
98 : friend class LayerImplSelect;
99 : struct ev_timer mLibEvTimer;
100 : #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH
101 :
102 : // Not defined
103 : TimerData(const TimerData &) = delete;
104 : TimerData & operator=(const TimerData &) = delete;
105 : };
106 :
107 : /**
108 : * List of `Timer`s ordered by expiration time.
109 : */
110 : class TimerList
111 : {
112 : public:
113 : class Node : public TimerData
114 : {
115 : public:
116 4133046 : Node(Layer & systemLayer, System::Clock::Timestamp awakenTime, TimerCompleteCallback onComplete, void * appState) :
117 4133046 : TimerData(systemLayer, awakenTime, onComplete, appState), mNextTimer(nullptr)
118 4133046 : {}
119 : Node * mNextTimer;
120 : };
121 :
122 0 : TimerList() : mEarliestTimer(nullptr) {}
123 :
124 : /**
125 : * Add a timer to the list
126 : *
127 : * @return The new earliest timer in the list. If this is the newly added timer, that implies it is earlier
128 : * than any existing timer.
129 : */
130 : Node * Add(Node * timer);
131 :
132 : /**
133 : * Remove the given timer from the list, if present. It is not an error for the timer not to be present.
134 : *
135 : * @return The new earliest timer in the list, or nullptr if the list is empty.
136 : */
137 : Node * Remove(Node * remove);
138 :
139 : /**
140 : * Remove the first timer with the given properties, if present. It is not an error for no such timer to be present.
141 : *
142 : * @return The removed timer, or nullptr if the list contains no matching timer.
143 : */
144 : Node * Remove(TimerCompleteCallback onComplete, void * appState);
145 :
146 : /**
147 : * Remove and return the earliest timer in the list.
148 : *
149 : * @return The earliest timer, or nullptr if the list is empty.
150 : */
151 : Node * PopEarliest();
152 :
153 : /**
154 : * Remove and return the earliest timer in the list, provided it expires earlier than the given time @a t.
155 : *
156 : * @return The earliest timer expiring before @a t, or nullptr if there is no such timer.
157 : */
158 : Node * PopIfEarlier(Clock::Timestamp t);
159 :
160 : /**
161 : * Get the earliest timer in the list.
162 : *
163 : * @return The earliest timer, or nullptr if there are no timers.
164 : */
165 4092511 : Node * Earliest() const { return mEarliestTimer; }
166 :
167 : /**
168 : * Test whether there are any timers.
169 : */
170 4092509 : bool Empty() const { return mEarliestTimer == nullptr; }
171 :
172 : /**
173 : * Remove and return all timers that expire before the given time @a t.
174 : */
175 : TimerList ExtractEarlier(Clock::Timestamp t);
176 :
177 : /**
178 : * Remove all timers.
179 : */
180 79 : void Clear() { mEarliestTimer = nullptr; }
181 :
182 : /**
183 : * Find the timer with the given properties, if present, and return its remaining time
184 : *
185 : * @return The remaining time on this partifcular timer or 0 if not found.
186 : */
187 : Clock::Timeout GetRemainingTime(TimerCompleteCallback aOnComplete, void * aAppState);
188 :
189 : private:
190 : Node * mEarliestTimer;
191 : };
192 :
193 : /**
194 : * ObjectPool wrapper that keeps System Timer statistics.
195 : */
196 : template <typename T = TimerList::Node>
197 : class TimerPool
198 : {
199 : public:
200 : using Timer = T;
201 :
202 : /**
203 : * Create a new timer from the pool.
204 : */
205 4133046 : Timer * Create(Layer & systemLayer, System::Clock::Timestamp awakenTime, TimerCompleteCallback onComplete, void * appState)
206 : {
207 4133046 : Timer * timer = mTimerPool.CreateObject(systemLayer, awakenTime, onComplete, appState);
208 4133046 : SYSTEM_STATS_INCREMENT(Stats::kSystemLayer_NumTimers);
209 4133046 : return timer;
210 : }
211 :
212 : /**
213 : * Release a timer to the pool.
214 : */
215 4133008 : void Release(Timer * timer)
216 : {
217 4133008 : SYSTEM_STATS_DECREMENT(Stats::kSystemLayer_NumTimers);
218 4133008 : mTimerPool.ReleaseObject(timer);
219 4133008 : }
220 :
221 : /**
222 : * Release all timers.
223 : */
224 79 : void ReleaseAll()
225 : {
226 79 : SYSTEM_STATS_RESET(Stats::kSystemLayer_NumTimers);
227 79 : mTimerPool.ReleaseAll();
228 79 : }
229 :
230 : /**
231 : * Release a timer to the pool and invoke its callback.
232 : */
233 11339 : void Invoke(Timer * timer)
234 : {
235 11339 : typename Timer::Callback callback = timer->GetCallback();
236 11339 : Release(timer);
237 11339 : callback.Invoke();
238 11339 : }
239 :
240 : private:
241 : friend class TestTimer;
242 : ObjectPool<Timer, CHIP_SYSTEM_CONFIG_NUM_TIMERS> mTimerPool;
243 : };
244 :
245 : } // namespace System
246 : } // namespace chip
|