18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#ifndef META_API_TIMER_H
178bf80f4bSopenharmony_ci#define META_API_TIMER_H
188bf80f4bSopenharmony_ci
198bf80f4bSopenharmony_ci#include <meta/api/deferred_callback.h>
208bf80f4bSopenharmony_ci#include <meta/api/make_callback.h>
218bf80f4bSopenharmony_ci#include <meta/api/threading/mutex.h>
228bf80f4bSopenharmony_ci#include <meta/interface/intf_task_queue.h>
238bf80f4bSopenharmony_ci#include <meta/interface/intf_task_queue_registry.h>
248bf80f4bSopenharmony_ci
258bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE()
268bf80f4bSopenharmony_ci
278bf80f4bSopenharmony_ci/**
288bf80f4bSopenharmony_ci * @brief Helper class to launch timers, this type is not copyable, only movable. Destructor will stop the timer.
298bf80f4bSopenharmony_ci */
308bf80f4bSopenharmony_ciclass Timer {
318bf80f4bSopenharmony_cipublic:
328bf80f4bSopenharmony_ci    /**
338bf80f4bSopenharmony_ci     * @brief Type of the timer, single shot happens only once when as recurring keeps triggering after given timeout
348bf80f4bSopenharmony_ci     */
358bf80f4bSopenharmony_ci    enum TimerType { SINGLE_SHOT, RECURRING };
368bf80f4bSopenharmony_ci
378bf80f4bSopenharmony_ci    Timer() = default;
388bf80f4bSopenharmony_ci    Timer(const Timer&) = delete;
398bf80f4bSopenharmony_ci    Timer(Timer&& t) : control_(BASE_NS::move(t.control_)) {}
408bf80f4bSopenharmony_ci    ~Timer()
418bf80f4bSopenharmony_ci    {
428bf80f4bSopenharmony_ci        Stop();
438bf80f4bSopenharmony_ci    }
448bf80f4bSopenharmony_ci
458bf80f4bSopenharmony_ci    /**
468bf80f4bSopenharmony_ci     * @brief Constructor that calls corresponding Start function (See Start below).
478bf80f4bSopenharmony_ci     */
488bf80f4bSopenharmony_ci    template<typename Func>
498bf80f4bSopenharmony_ci    Timer(const TimeSpan& interval, Func func, TimerType type, const ITaskQueue::Ptr& queue)
508bf80f4bSopenharmony_ci    {
518bf80f4bSopenharmony_ci        Start(interval, BASE_NS::move(func), type, queue);
528bf80f4bSopenharmony_ci    }
538bf80f4bSopenharmony_ci
548bf80f4bSopenharmony_ci    /**
558bf80f4bSopenharmony_ci     * @brief Constructor that calls corresponding Start function (See Start below).
568bf80f4bSopenharmony_ci     */
578bf80f4bSopenharmony_ci    template<typename Func>
588bf80f4bSopenharmony_ci    Timer(const TimeSpan& interval, Func func, TimerType type, const BASE_NS::Uid& queueId)
598bf80f4bSopenharmony_ci    {
608bf80f4bSopenharmony_ci        Start(interval, BASE_NS::move(func), type, queueId);
618bf80f4bSopenharmony_ci    }
628bf80f4bSopenharmony_ci
638bf80f4bSopenharmony_ci    Timer& operator=(const Timer&) = delete;
648bf80f4bSopenharmony_ci    Timer& operator=(Timer&& t)
658bf80f4bSopenharmony_ci    {
668bf80f4bSopenharmony_ci        Stop();
678bf80f4bSopenharmony_ci        control_ = BASE_NS::move(t.control_);
688bf80f4bSopenharmony_ci        return *this;
698bf80f4bSopenharmony_ci    }
708bf80f4bSopenharmony_ci
718bf80f4bSopenharmony_ci    /**
728bf80f4bSopenharmony_ci     * @brief Start timer.
738bf80f4bSopenharmony_ci     * @param interval Time interval which after this timer triggers.
748bf80f4bSopenharmony_ci     * @param func Callable entity (e.g. lambda) which is called.
758bf80f4bSopenharmony_ci     * @param type Type of the timer.
768bf80f4bSopenharmony_ci     * @param queue Queue to which the timer task is posted to (this dictates on what thread the func is called).
778bf80f4bSopenharmony_ci     */
788bf80f4bSopenharmony_ci    template<typename Func>
798bf80f4bSopenharmony_ci    bool Start(const TimeSpan& interval, Func func, TimerType type, const ITaskQueue::Ptr& queue)
808bf80f4bSopenharmony_ci    {
818bf80f4bSopenharmony_ci        if (!queue) {
828bf80f4bSopenharmony_ci            return false;
838bf80f4bSopenharmony_ci        }
848bf80f4bSopenharmony_ci        Stop();
858bf80f4bSopenharmony_ci        control_ = CreateShared<Control>();
868bf80f4bSopenharmony_ci        control_->queue = queue;
878bf80f4bSopenharmony_ci        control_->token =
888bf80f4bSopenharmony_ci            queue->AddTask(MakeCallback<ITaskQueueTask>([control = control_, type, callback = BASE_NS::move(func)] {
898bf80f4bSopenharmony_ci                callback();
908bf80f4bSopenharmony_ci                bool ret = type == RECURRING;
918bf80f4bSopenharmony_ci                if (!ret) {
928bf80f4bSopenharmony_ci                    if (control) {
938bf80f4bSopenharmony_ci                        CORE_NS::UniqueLock lock { control->mutex };
948bf80f4bSopenharmony_ci                        control->token = {};
958bf80f4bSopenharmony_ci                    }
968bf80f4bSopenharmony_ci                }
978bf80f4bSopenharmony_ci                return ret;
988bf80f4bSopenharmony_ci            }),
998bf80f4bSopenharmony_ci                interval);
1008bf80f4bSopenharmony_ci        return true;
1018bf80f4bSopenharmony_ci    }
1028bf80f4bSopenharmony_ci
1038bf80f4bSopenharmony_ci    /**
1048bf80f4bSopenharmony_ci     * @brief Start timer.
1058bf80f4bSopenharmony_ci     * @param interval Time interval which after this timer triggers.
1068bf80f4bSopenharmony_ci     * @param func Callable entity (e.g. lambda) which is called.
1078bf80f4bSopenharmony_ci     * @param type Type of the timer.
1088bf80f4bSopenharmony_ci     * @param queueId Uid of queue to which the timer task is posted to (this dictates on what thread the func is
1098bf80f4bSopenharmony_ci     * called).
1108bf80f4bSopenharmony_ci     */
1118bf80f4bSopenharmony_ci    template<typename Func>
1128bf80f4bSopenharmony_ci    bool Start(const TimeSpan& interval, Func func, TimerType type, const BASE_NS::Uid& queueId)
1138bf80f4bSopenharmony_ci    {
1148bf80f4bSopenharmony_ci        return Start(interval, BASE_NS::move(func), type, GetTaskQueueRegistry().GetTaskQueue(queueId));
1158bf80f4bSopenharmony_ci    }
1168bf80f4bSopenharmony_ci
1178bf80f4bSopenharmony_ci    /**
1188bf80f4bSopenharmony_ci     * @brief Stop timer
1198bf80f4bSopenharmony_ci     */
1208bf80f4bSopenharmony_ci    void Stop()
1218bf80f4bSopenharmony_ci    {
1228bf80f4bSopenharmony_ci        if (control_) {
1238bf80f4bSopenharmony_ci            CORE_NS::UniqueLock lock { control_->mutex };
1248bf80f4bSopenharmony_ci            if (control_->queue && control_->token) {
1258bf80f4bSopenharmony_ci                control_->queue->CancelTask(control_->token);
1268bf80f4bSopenharmony_ci            }
1278bf80f4bSopenharmony_ci        }
1288bf80f4bSopenharmony_ci        control_.reset();
1298bf80f4bSopenharmony_ci    }
1308bf80f4bSopenharmony_ci
1318bf80f4bSopenharmony_ci    /**
1328bf80f4bSopenharmony_ci     * @brief Detach timer, this can be used if you don't want destructor to stop the timer
1338bf80f4bSopenharmony_ci     */
1348bf80f4bSopenharmony_ci    ITaskQueue::Token Detach()
1358bf80f4bSopenharmony_ci    {
1368bf80f4bSopenharmony_ci        ITaskQueue::Token ret {};
1378bf80f4bSopenharmony_ci        if (control_) {
1388bf80f4bSopenharmony_ci            CORE_NS::UniqueLock lock { control_->mutex };
1398bf80f4bSopenharmony_ci            ret = control_->token;
1408bf80f4bSopenharmony_ci        }
1418bf80f4bSopenharmony_ci        control_.reset();
1428bf80f4bSopenharmony_ci        return ret;
1438bf80f4bSopenharmony_ci    }
1448bf80f4bSopenharmony_ci
1458bf80f4bSopenharmony_ci    /**
1468bf80f4bSopenharmony_ci     * @brief Returns true if the timer is currently running
1478bf80f4bSopenharmony_ci     */
1488bf80f4bSopenharmony_ci    bool IsRunning() const
1498bf80f4bSopenharmony_ci    {
1508bf80f4bSopenharmony_ci        if (control_) {
1518bf80f4bSopenharmony_ci            CORE_NS::UniqueLock lock { control_->mutex };
1528bf80f4bSopenharmony_ci            return control_->token != ITaskQueue::Token {};
1538bf80f4bSopenharmony_ci        }
1548bf80f4bSopenharmony_ci        return false;
1558bf80f4bSopenharmony_ci    }
1568bf80f4bSopenharmony_ci
1578bf80f4bSopenharmony_ciprivate:
1588bf80f4bSopenharmony_ci    struct Control {
1598bf80f4bSopenharmony_ci        mutable CORE_NS::Mutex mutex;
1608bf80f4bSopenharmony_ci        ITaskQueue::Ptr queue;
1618bf80f4bSopenharmony_ci        ITaskQueue::Token token {};
1628bf80f4bSopenharmony_ci    };
1638bf80f4bSopenharmony_ci    BASE_NS::shared_ptr<Control> control_;
1648bf80f4bSopenharmony_ci};
1658bf80f4bSopenharmony_ci
1668bf80f4bSopenharmony_ci/**
1678bf80f4bSopenharmony_ci * @brief Start single shot timer, returns the token that can be used to cancel it (which can be just ignored).
1688bf80f4bSopenharmony_ci * @param interval Time interval which after this timer triggers.
1698bf80f4bSopenharmony_ci * @param func Callable entity (e.g. lambda) which is called.
1708bf80f4bSopenharmony_ci * @param queue Queue to which the timer task is posted to (this dictates on what thread the func is called).
1718bf80f4bSopenharmony_ci */
1728bf80f4bSopenharmony_citemplate<typename Func>
1738bf80f4bSopenharmony_ciinline ITaskQueue::Token SingleShotTimer(const TimeSpan& interval, Func func, const ITaskQueue::Ptr& queue)
1748bf80f4bSopenharmony_ci{
1758bf80f4bSopenharmony_ci    Timer t;
1768bf80f4bSopenharmony_ci    t.Start(interval, BASE_NS::move(func), Timer::SINGLE_SHOT, queue);
1778bf80f4bSopenharmony_ci    return t.Detach();
1788bf80f4bSopenharmony_ci}
1798bf80f4bSopenharmony_ci
1808bf80f4bSopenharmony_ci/**
1818bf80f4bSopenharmony_ci * @brief Start single shot timer, returns the token that can be used to cancel it (which can be just ignored).
1828bf80f4bSopenharmony_ci * @param interval Time interval which after this timer triggers.
1838bf80f4bSopenharmony_ci * @param func Callable entity (e.g. lambda) which is called.
1848bf80f4bSopenharmony_ci * @param queueId Uid of queue to which the timer task is posted to (this dictates on what thread the func is called).
1858bf80f4bSopenharmony_ci */
1868bf80f4bSopenharmony_citemplate<typename Func>
1878bf80f4bSopenharmony_ciinline ITaskQueue::Token SingleShotTimer(const TimeSpan& interval, Func func, const BASE_NS::Uid& queueId)
1888bf80f4bSopenharmony_ci{
1898bf80f4bSopenharmony_ci    Timer t;
1908bf80f4bSopenharmony_ci    t.Start(interval, BASE_NS::move(func), Timer::SINGLE_SHOT, queueId);
1918bf80f4bSopenharmony_ci    return t.Detach();
1928bf80f4bSopenharmony_ci}
1938bf80f4bSopenharmony_ci
1948bf80f4bSopenharmony_ciMETA_END_NAMESPACE()
1958bf80f4bSopenharmony_ci
1968bf80f4bSopenharmony_ci#endif
197