/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef META_API_TIMER_H
#define META_API_TIMER_H
#include
#include
#include
#include
#include
META_BEGIN_NAMESPACE()
/**
* @brief Helper class to launch timers, this type is not copyable, only movable. Destructor will stop the timer.
*/
class Timer {
public:
/**
* @brief Type of the timer, single shot happens only once when as recurring keeps triggering after given timeout
*/
enum TimerType { SINGLE_SHOT, RECURRING };
Timer() = default;
Timer(const Timer&) = delete;
Timer(Timer&& t) : control_(BASE_NS::move(t.control_)) {}
~Timer()
{
Stop();
}
/**
* @brief Constructor that calls corresponding Start function (See Start below).
*/
template
Timer(const TimeSpan& interval, Func func, TimerType type, const ITaskQueue::Ptr& queue)
{
Start(interval, BASE_NS::move(func), type, queue);
}
/**
* @brief Constructor that calls corresponding Start function (See Start below).
*/
template
Timer(const TimeSpan& interval, Func func, TimerType type, const BASE_NS::Uid& queueId)
{
Start(interval, BASE_NS::move(func), type, queueId);
}
Timer& operator=(const Timer&) = delete;
Timer& operator=(Timer&& t)
{
Stop();
control_ = BASE_NS::move(t.control_);
return *this;
}
/**
* @brief Start timer.
* @param interval Time interval which after this timer triggers.
* @param func Callable entity (e.g. lambda) which is called.
* @param type Type of the timer.
* @param queue Queue to which the timer task is posted to (this dictates on what thread the func is called).
*/
template
bool Start(const TimeSpan& interval, Func func, TimerType type, const ITaskQueue::Ptr& queue)
{
if (!queue) {
return false;
}
Stop();
control_ = CreateShared();
control_->queue = queue;
control_->token =
queue->AddTask(MakeCallback([control = control_, type, callback = BASE_NS::move(func)] {
callback();
bool ret = type == RECURRING;
if (!ret) {
if (control) {
CORE_NS::UniqueLock lock { control->mutex };
control->token = {};
}
}
return ret;
}),
interval);
return true;
}
/**
* @brief Start timer.
* @param interval Time interval which after this timer triggers.
* @param func Callable entity (e.g. lambda) which is called.
* @param type Type of the timer.
* @param queueId Uid of queue to which the timer task is posted to (this dictates on what thread the func is
* called).
*/
template
bool Start(const TimeSpan& interval, Func func, TimerType type, const BASE_NS::Uid& queueId)
{
return Start(interval, BASE_NS::move(func), type, GetTaskQueueRegistry().GetTaskQueue(queueId));
}
/**
* @brief Stop timer
*/
void Stop()
{
if (control_) {
CORE_NS::UniqueLock lock { control_->mutex };
if (control_->queue && control_->token) {
control_->queue->CancelTask(control_->token);
}
}
control_.reset();
}
/**
* @brief Detach timer, this can be used if you don't want destructor to stop the timer
*/
ITaskQueue::Token Detach()
{
ITaskQueue::Token ret {};
if (control_) {
CORE_NS::UniqueLock lock { control_->mutex };
ret = control_->token;
}
control_.reset();
return ret;
}
/**
* @brief Returns true if the timer is currently running
*/
bool IsRunning() const
{
if (control_) {
CORE_NS::UniqueLock lock { control_->mutex };
return control_->token != ITaskQueue::Token {};
}
return false;
}
private:
struct Control {
mutable CORE_NS::Mutex mutex;
ITaskQueue::Ptr queue;
ITaskQueue::Token token {};
};
BASE_NS::shared_ptr control_;
};
/**
* @brief Start single shot timer, returns the token that can be used to cancel it (which can be just ignored).
* @param interval Time interval which after this timer triggers.
* @param func Callable entity (e.g. lambda) which is called.
* @param queue Queue to which the timer task is posted to (this dictates on what thread the func is called).
*/
template
inline ITaskQueue::Token SingleShotTimer(const TimeSpan& interval, Func func, const ITaskQueue::Ptr& queue)
{
Timer t;
t.Start(interval, BASE_NS::move(func), Timer::SINGLE_SHOT, queue);
return t.Detach();
}
/**
* @brief Start single shot timer, returns the token that can be used to cancel it (which can be just ignored).
* @param interval Time interval which after this timer triggers.
* @param func Callable entity (e.g. lambda) which is called.
* @param queueId Uid of queue to which the timer task is posted to (this dictates on what thread the func is called).
*/
template
inline ITaskQueue::Token SingleShotTimer(const TimeSpan& interval, Func func, const BASE_NS::Uid& queueId)
{
Timer t;
t.Start(interval, BASE_NS::move(func), Timer::SINGLE_SHOT, queueId);
return t.Detach();
}
META_END_NAMESPACE()
#endif