Coverage Report

Created: 2026-07-10 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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