13f4cbf05Sopenharmony_ci/* 23f4cbf05Sopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd. 33f4cbf05Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43f4cbf05Sopenharmony_ci * you may not use this file except in compliance with the License. 53f4cbf05Sopenharmony_ci * You may obtain a copy of the License at 63f4cbf05Sopenharmony_ci * 73f4cbf05Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83f4cbf05Sopenharmony_ci * 93f4cbf05Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103f4cbf05Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113f4cbf05Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123f4cbf05Sopenharmony_ci * See the License for the specific language governing permissions and 133f4cbf05Sopenharmony_ci * limitations under the License. 143f4cbf05Sopenharmony_ci */ 153f4cbf05Sopenharmony_ci 163f4cbf05Sopenharmony_ci#ifndef UTILS_TIMER_H 173f4cbf05Sopenharmony_ci#define UTILS_TIMER_H 183f4cbf05Sopenharmony_ci 193f4cbf05Sopenharmony_ci#include <sys/types.h> 203f4cbf05Sopenharmony_ci#include <cstdint> 213f4cbf05Sopenharmony_ci#include <string> 223f4cbf05Sopenharmony_ci#include <list> 233f4cbf05Sopenharmony_ci#include <map> 243f4cbf05Sopenharmony_ci#include <mutex> 253f4cbf05Sopenharmony_ci#include <thread> 263f4cbf05Sopenharmony_ci#include <vector> 273f4cbf05Sopenharmony_ci 283f4cbf05Sopenharmony_cinamespace OHOS { 293f4cbf05Sopenharmony_cinamespace Utils { 303f4cbf05Sopenharmony_ciclass EventReactor; 313f4cbf05Sopenharmony_ci/** 323f4cbf05Sopenharmony_ci * @brief Implements a timer manager. 333f4cbf05Sopenharmony_ci * 343f4cbf05Sopenharmony_ci * After a timer is started, users can register several timed events, which 353f4cbf05Sopenharmony_ci * can be continuous or one-shot, to it. Some points need to be noticed:\n 363f4cbf05Sopenharmony_ci * 1. A timer must be set up (through Setup()) before use, and be shut down 373f4cbf05Sopenharmony_ci * (via Shutdown()) before its deconstruction.\n 383f4cbf05Sopenharmony_ci * 2. A timer must be set up first and then shut down. Avoid delegating a 393f4cbf05Sopenharmony_ci * timer to different threads. Otherwise, multithreading issues may occur.\n 403f4cbf05Sopenharmony_ci * 3. Setting up a timer again will not reset the timer, but return 413f4cbf05Sopenharmony_ci * `TIMER_ERR_INVALID_VALUE`. If a reset operation is required, shut down 423f4cbf05Sopenharmony_ci * the timer first and then set it up.\n 433f4cbf05Sopenharmony_ci * 4. The parameter in Shutdown() determines whether the thread in the timer 443f4cbf05Sopenharmony_ci * will be detached. A detach operation may cause possible 453f4cbf05Sopenharmony_ci * multithreading problems, and is therefore not recommended. If a 463f4cbf05Sopenharmony_ci * detach operation is required, availability of related objects used in 473f4cbf05Sopenharmony_ci * `thread_` must be guaranteed. 483f4cbf05Sopenharmony_ci */ 493f4cbf05Sopenharmony_ciclass Timer { 503f4cbf05Sopenharmony_cipublic: 513f4cbf05Sopenharmony_ci using TimerCallback = std::function<void ()>; 523f4cbf05Sopenharmony_ci using TimerCallbackPtr = std::shared_ptr<TimerCallback>; 533f4cbf05Sopenharmony_ci using TimerListCallback = std::function<void (int timerFd)>; 543f4cbf05Sopenharmony_ci 553f4cbf05Sopenharmony_cipublic: 563f4cbf05Sopenharmony_ci /** 573f4cbf05Sopenharmony_ci * @brief Creates a timer. 583f4cbf05Sopenharmony_ci * 593f4cbf05Sopenharmony_ci * In performance-sensitive scenarios, set `timeoutMs` to a 603f4cbf05Sopenharmony_ci * greater value before timer setup based on your timed event setttings. The 613f4cbf05Sopenharmony_ci * default value is 1000 ms. The timeout event requires 100 us to respond. 623f4cbf05Sopenharmony_ci * 633f4cbf05Sopenharmony_ci * @param name Indicates the name of the timer. It is used as the name 643f4cbf05Sopenharmony_ci * of the thread in the timer. 653f4cbf05Sopenharmony_ci * @param timeoutMs Indicates the duration for which the timer will wait. 663f4cbf05Sopenharmony_ci * The value is an integer in [-1, INT32MAX], but `-1` and `0` are not 673f4cbf05Sopenharmony_ci * recommended. `-1` means to wait indefinitely (until the timed event is 683f4cbf05Sopenharmony_ci * triggered). `0` means not to wait, which occupies too much CPU time. 693f4cbf05Sopenharmony_ci */ 703f4cbf05Sopenharmony_ci explicit Timer(const std::string& name, int timeoutMs = 1000); 713f4cbf05Sopenharmony_ci virtual ~Timer(); 723f4cbf05Sopenharmony_ci 733f4cbf05Sopenharmony_ci /** 743f4cbf05Sopenharmony_ci * @brief Sets up a timer. 753f4cbf05Sopenharmony_ci * 763f4cbf05Sopenharmony_ci * Do not set up a timer before shutting down the existing one. 773f4cbf05Sopenharmony_ci */ 783f4cbf05Sopenharmony_ci virtual uint32_t Setup(); 793f4cbf05Sopenharmony_ci 803f4cbf05Sopenharmony_ci /** 813f4cbf05Sopenharmony_ci * @brief Shuts down this timer. 823f4cbf05Sopenharmony_ci * 833f4cbf05Sopenharmony_ci * A timer can be shut down in blocking or unblocking mode. In blocking 843f4cbf05Sopenharmony_ci * mode, the timer will be shut down only after all running events 853f4cbf05Sopenharmony_ci * in the timer have finished. If `timeoutMs` is set to `-1`, use 863f4cbf05Sopenharmony_ci * unblocking mode to avoid deadloop. 873f4cbf05Sopenharmony_ci * 883f4cbf05Sopenharmony_ci * @param useJoin Specifies whether to use blocking mode. The value `true` 893f4cbf05Sopenharmony_ci * means to use blocking mode, and `false` (not recommended) means 903f4cbf05Sopenharmony_ci * the opposite. 913f4cbf05Sopenharmony_ci */ 923f4cbf05Sopenharmony_ci virtual void Shutdown(bool useJoin = true); 933f4cbf05Sopenharmony_ci 943f4cbf05Sopenharmony_ci /** 953f4cbf05Sopenharmony_ci * @brief Registers timed events. 963f4cbf05Sopenharmony_ci * 973f4cbf05Sopenharmony_ci * @param callback Indicates the callback function of a timed event. 983f4cbf05Sopenharmony_ci * @param interval Indicates the interval of a timed event, in ms. 993f4cbf05Sopenharmony_ci * @param once Indicates whether the timed event is one-shot. 1003f4cbf05Sopenharmony_ci * The value `true` means that the timed event is one-shot, 1013f4cbf05Sopenharmony_ci * and `false` means the opposite. The default value is `false`. 1023f4cbf05Sopenharmony_ci * @return Returns the ID of a timed event. You can use it as the 1033f4cbf05Sopenharmony_ci * parameter of Unregister(). 1043f4cbf05Sopenharmony_ci * @see Unregister 1053f4cbf05Sopenharmony_ci */ 1063f4cbf05Sopenharmony_ci uint32_t Register(const TimerCallback& callback, uint32_t interval /* ms */, bool once = false); 1073f4cbf05Sopenharmony_ci /** 1083f4cbf05Sopenharmony_ci * @brief Deletes a timed event. 1093f4cbf05Sopenharmony_ci * 1103f4cbf05Sopenharmony_ci * @param timerId Indicates the ID of the timed event to delete. 1113f4cbf05Sopenharmony_ci * It can be obtained through Register(). 1123f4cbf05Sopenharmony_ci * @see Register 1133f4cbf05Sopenharmony_ci */ 1143f4cbf05Sopenharmony_ci void Unregister(uint32_t timerId); 1153f4cbf05Sopenharmony_ci 1163f4cbf05Sopenharmony_ciprivate: 1173f4cbf05Sopenharmony_ci void MainLoop(); 1183f4cbf05Sopenharmony_ci void OnTimer(int timerFd); 1193f4cbf05Sopenharmony_ci virtual uint32_t DoRegister(const TimerListCallback& callback, uint32_t interval, bool once, int &timerFd); 1203f4cbf05Sopenharmony_ci virtual void DoUnregister(uint32_t interval); 1213f4cbf05Sopenharmony_ci void DoTimerListCallback(const TimerListCallback& callback, int timerFd); 1223f4cbf05Sopenharmony_ci uint32_t GetValidId(uint32_t timerId) const; 1233f4cbf05Sopenharmony_ci int GetTimerFd(uint32_t interval /* ms */); 1243f4cbf05Sopenharmony_ci void EraseUnusedTimerId(uint32_t interval, const std::vector<uint32_t>& unusedIds); 1253f4cbf05Sopenharmony_ci 1263f4cbf05Sopenharmony_ciprivate: 1273f4cbf05Sopenharmony_ci struct TimerEntry { 1283f4cbf05Sopenharmony_ci uint32_t timerId; // Unique ID. 1293f4cbf05Sopenharmony_ci uint32_t interval; // million second 1303f4cbf05Sopenharmony_ci TimerCallback callback; 1313f4cbf05Sopenharmony_ci bool once; 1323f4cbf05Sopenharmony_ci int timerFd; 1333f4cbf05Sopenharmony_ci }; 1343f4cbf05Sopenharmony_ci 1353f4cbf05Sopenharmony_ci using TimerEntryPtr = std::shared_ptr<TimerEntry>; 1363f4cbf05Sopenharmony_ci using TimerEntryList = std::list<TimerEntryPtr>; 1373f4cbf05Sopenharmony_ci 1383f4cbf05Sopenharmony_ci std::map<uint32_t, TimerEntryList> intervalToTimers_; // interval to TimerEntryList 1393f4cbf05Sopenharmony_ci std::map<uint32_t, TimerEntryPtr> timerToEntries_; // timer_id to TimerEntry 1403f4cbf05Sopenharmony_ci 1413f4cbf05Sopenharmony_ci std::string name_; 1423f4cbf05Sopenharmony_ci int timeoutMs_; 1433f4cbf05Sopenharmony_ci std::thread thread_; 1443f4cbf05Sopenharmony_ci EventReactor *reactor_; 1453f4cbf05Sopenharmony_ci std::map<uint32_t, uint32_t> timers_; // timer_fd to interval 1463f4cbf05Sopenharmony_ci std::mutex mutex_; 1473f4cbf05Sopenharmony_ci}; 1483f4cbf05Sopenharmony_ci 1493f4cbf05Sopenharmony_ci} // namespace Utils 1503f4cbf05Sopenharmony_ci} // namespace OHOS 1513f4cbf05Sopenharmony_ci#endif 1523f4cbf05Sopenharmony_ci 153