Kodi Development 19.0
for Binary and Script based Add-Ons
Timer.h
1/*
2 * Copyright (C) 2005-2020 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9#pragma once
10
11#ifdef __cplusplus
12
13#include "Thread.h"
14
15#include <functional>
16
17namespace kodi
18{
19namespace tools
20{
21
22//==============================================================================
58class CTimer : protected CThread
59{
60public:
61 class ITimerCallback;
62
63 //============================================================================
71 : CTimer(std::bind(&ITimerCallback::OnTimeout, callback))
72 {
73 }
74 //----------------------------------------------------------------------------
75
76 //============================================================================
88 explicit CTimer(std::function<void()> const& callback) : m_callback(callback) {}
89 //----------------------------------------------------------------------------
90
91 //============================================================================
95 ~CTimer() override { Stop(true); }
96 //----------------------------------------------------------------------------
97
98 //============================================================================
112 bool Start(uint64_t timeout, bool interval = false)
113 {
114 using namespace std::chrono;
115
116 if (m_callback == nullptr || timeout == 0 || IsRunning())
117 return false;
118
119 m_timeout = milliseconds(timeout);
120 m_interval = interval;
121
122 CreateThread();
123 return true;
124 }
125 //----------------------------------------------------------------------------
126
127 //============================================================================
136 bool Stop(bool wait = false)
137 {
138 if (!IsRunning())
139 return false;
140
141 m_threadStop = true;
142 m_eventTimeout.notify_all();
143 StopThread(wait);
144
145 return true;
146 }
147 //----------------------------------------------------------------------------
148
149 //============================================================================
159 bool Restart()
160 {
161 using namespace std::chrono;
162
163 if (!IsRunning())
164 return false;
165
166 Stop(true);
167 return Start(duration_cast<milliseconds>(m_timeout).count(), m_interval);
168 }
169 //----------------------------------------------------------------------------
170
171 //============================================================================
177 void RestartAsync(uint64_t timeout)
178 {
179 using namespace std::chrono;
180
181 m_timeout = milliseconds(timeout);
182 const auto now = system_clock::now();
183 m_endTime = now.time_since_epoch() + m_timeout;
184 m_eventTimeout.notify_all();
185 }
186 //----------------------------------------------------------------------------
187
188 //============================================================================
194 bool IsRunning() const { return CThread::IsRunning(); }
195 //----------------------------------------------------------------------------
196
197 //============================================================================
203 float GetElapsedSeconds() const { return GetElapsedMilliseconds() / 1000.0f; }
204 //----------------------------------------------------------------------------
205
206 //============================================================================
213 {
214 using namespace std::chrono;
215
216 if (!IsRunning())
217 return 0.0f;
218
219 const auto now = system_clock::now();
220 return static_cast<float>(duration_cast<milliseconds>(now.time_since_epoch() - (m_endTime - m_timeout)).count());
221 }
222 //----------------------------------------------------------------------------
223
224 //============================================================================
231 {
232 public:
233 //==========================================================================
237 virtual ~ITimerCallback() = default;
238 //--------------------------------------------------------------------------
239
240 //==========================================================================
267 virtual void OnTimeout() = 0;
268 //--------------------------------------------------------------------------
269 };
270 //----------------------------------------------------------------------------
271
272protected:
273 void Process() override
274 {
275 using namespace std::chrono;
276
277 while (!m_threadStop)
278 {
279 auto currentTime = system_clock::now();
280 m_endTime = currentTime.time_since_epoch() + m_timeout;
281
282 // wait the necessary time
283 std::mutex mutex;
284 std::unique_lock<std::mutex> lock(mutex);
285 const auto waitTime = duration_cast<milliseconds>(m_endTime - currentTime.time_since_epoch());
286 if (m_eventTimeout.wait_for(lock, waitTime) == std::cv_status::timeout)
287 {
288 currentTime = system_clock::now();
289 if (m_endTime.count() <= currentTime.time_since_epoch().count())
290 {
291 // execute OnTimeout() callback
292 m_callback();
293
294 // continue if this is an interval timer, or if it was restarted during callback
295 if (!m_interval && m_endTime.count() <= currentTime.time_since_epoch().count())
296 break;
297 }
298 }
299 }
300 }
301
302private:
303 bool m_interval = false;
304 std::function<void()> m_callback;
305 std::chrono::system_clock::duration m_timeout;
306 std::chrono::system_clock::duration m_endTime;
307 std::condition_variable_any m_eventTimeout;
308};
310//------------------------------------------------------------------------------
311
312} /* namespace tools */
313} /* namespace kodi */
314
315#endif /* __cplusplus */
Definition: Thread.h:91
Definition: Timer.h:59
void Process() override
The function to be added by the addon as a child to carry out the process thread.
Definition: Timer.h:273
std::atomic< bool > m_threadStop
Atomic bool to indicate thread is active.
Definition: Thread.h:380
void StopThread(bool wait=true)
Stop a running thread.
Definition: Thread.h:266
bool IsRunning() const
Check thread inside this class is running and active.
Definition: Thread.h:143
void CreateThread(bool autoDelete=false)
Create a new thread defined by this class on child.
Definition: Thread.h:170
virtual ~ITimerCallback()=default
Class destructor.
virtual void OnTimeout()=0
Callback function to implement if constuctor CTimer(kodi::tools::CTimer::ITimerCallback* callback) is...
void RestartAsync(uint64_t timeout)
Restart the timer with new timeout without touch of his thread.
Definition: Timer.h:177
float GetElapsedSeconds() const
Get elapsed time as floating point of timer as seconds.
Definition: Timer.h:203
bool Start(uint64_t timeout, bool interval=false)
Start the timer by given time in milliseconds to make his call by arrive of them.
Definition: Timer.h:112
bool Stop(bool wait=false)
Stop the timer if it is active.
Definition: Timer.h:136
bool Restart()
Restart timer complete by stop and restart his thread again.
Definition: Timer.h:159
CTimer(kodi::tools::CTimer::ITimerCallback *callback)
Class constructor to pass individual other class as callback.
Definition: Timer.h:70
~CTimer() override
Class destructor.
Definition: Timer.h:95
bool IsRunning() const
Check timer is still active to wait for next call.
Definition: Timer.h:194
float GetElapsedMilliseconds() const
Get elapsed time as floating point of timer as milliseconds.
Definition: Timer.h:212
CTimer(std::function< void()> const &callback)
Class constructor to pass individual function as callback.
Definition: Timer.h:88