/*! \file pitimer.h * \ingroup Thread * \~\brief * \~english Timer * \~russian Таймер */ /* PIP - Platform Independent Primitives Timer Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PITIMER_H #define PITIMER_H #include "piconditionvar.h" #include "piobject.h" #include "pisystemtime.h" class PIThread; class PIP_EXPORT PITimer: public PIObject { PIOBJECT_SUBCLASS(PITimer, PIObject); public: NO_COPY_CLASS(PITimer); //! \~english Constructs timer //! \~russian Создает таймер explicit PITimer(); //! \~english Constructs timer with method void(int) //! \~russian Создает таймер с функцией void(int) explicit PITimer(std::function func); //! \~english Constructs timer with method void() //! \~russian Создает таймер с функцией void() explicit PITimer(std::function func); virtual ~PITimer(); //! \~english Returns timer loop delay //! \~russian Возвращает задержку цикла таймера PISystemTime interval() const; //! \~english Set timer loop delay //! \~russian Установить интервал таймера void setInterval(PISystemTime interval); //! \~english Returns if timer is started //! \~russian Возвращает работает ли таймер bool isRunning() const; //! \~english Return if timer is stopping //! \~russian Возвращает останавливается ли таймер bool isStopping() const; //! \~english Wait for timer stop //! \~russian Ожидает остановки таймера bool waitForFinish(PISystemTime timeout = {}); //! \~english Start timer with "interval" loop delay //! \~russian Запустить таймер с интервалом "interval" bool start(PISystemTime interval); //! \~english Start timer with "interval" loop delay and tick function "func" //! \~russian Запустить таймер с интервалом "interval" и вызываевымым методом "func" bool start(PISystemTime interval, std::function func); bool start(double interval_ms) DEPRECATEDM("use start(PISystemTime)") { return start(PISystemTime::fromMilliseconds(interval_ms)); } EVENT_HANDLER0(bool, start); EVENT_HANDLER0(bool, restart); EVENT_HANDLER0(void, stop); //! \~english Stop timer and wait for finish. //! \~russian Останавливает таймер и ожидает завершения. void stopAndWait(int timeout_ms) { stopAndWait(PISystemTime::fromMilliseconds(timeout_ms)); } //! \~english Stop timer and wait for finish. //! \~russian Останавливает таймер и ожидает завершения. void stopAndWait(PISystemTime timeout = {}); //! \~english Set timer tick function //! \~russian Установить вызываемый метод void setSlot(std::function func) { ret_func = [func](int) { func(); }; } //! \~english Set timer tick function //! \~russian Установить вызываемый метод void setSlot(std::function func) { ret_func = func; } void needLockRun(bool need) { lockRun = need; } EVENT_HANDLER0(void, lock) { mutex_.lock(); } EVENT_HANDLER0(void, unlock) { mutex_.unlock(); } //! \~english Returns if timer should exec \a maybeCallQueuedEvents() at every tick. By default \b true //! \~russian Возвращает должен ли таймер вызывать \a maybeCallQueuedEvents() каждый тик. По умолчанию \b true bool isCallQueuedEvents() const { return callEvents; } //! \~english Set timer exec \a maybeCallQueuedEvents() at every tick //! \~russian Установает должен ли таймер вызывать \a maybeCallQueuedEvents() каждый тик void setCallQueuedEvents(bool yes) { callEvents = yes; } //! \~english Add frequency delimiter "delim" with optional delimiter slot "slot" //! \~russian Добавляет делитель частоты "delim" с необязательным методом "slot" void addDelimiter(int delim, std::function func = nullptr); //! \~english Add frequency delimiter "delim" with optional delimiter slot "slot" //! \~russian Добавляет делитель частоты "delim" с необязательным методом "slot" void addDelimiter(int delim, std::function func); //! \~english Add frequency delimiter "delim" with optional delimiter slot "slot" //! \~russian Добавляет делитель частоты "delim" с необязательным методом "slot" void addDelimiter(int delim, std::function slot); //! \~english Remove all frequency delimiters "delim" //! \~russian Удаляет все делители частоты "delim" void removeDelimiter(int delim); EVENT_HANDLER0(void, clearDelimiters) { delims.clear(); } EVENT1(tickEvent, int, delimiter); //! \handlers //! \{ //! \fn bool start() //! \brief //! \~english Start timer with \a interval() loop delay //! \~russian Запустить таймер с интервалом \a interval() //! \fn bool restart() //! \brief //! \~english Stop and start timer with \a interval() loop delay //! \~russian Остановить и запустить таймер с интервалом \a interval() //! \fn bool stop() //! \brief //! \~english Stop timer (don`t wait for finish) //! \~russian Остановить таймер (не дожидается остановки) //! \fn void clearDelimiters() //! \brief //! \~english Remove all frequency delimiters //! \~russian Удаляет все делители частоты //! \} //! \events //! \{ //! \fn void tickEvent(int delimiter) //! \brief //! \~english Raise on timer tick //! \~russian Вызывается каждый тик таймера //! \~\details //! \~english //! "delimiter" is frequency delimiter, 1 for main loop. //! \~russian //! "delimiter" - делитель частоты, 1 для основного цикла //! \} protected: struct PIP_EXPORT Delimiter { Delimiter(std::function func_ = nullptr, int delim_ = 1) { func = func_; delim = delim_; } std::function func; int delim = 0; int tick = 0; }; void initFirst(); void init() const; void threadFunc(); void adjustTimes(); void execTick(); //! Timer execution function, similar to "slot" or event \a timeout(). By default does nothing virtual void tick(int delimiter) {} PIThread * thread = nullptr; std::atomic_bool lockRun = {false}, callEvents = {true}; PIMutex mutex_; PISystemTime m_interval, m_interval_x5; PISystemTime m_time_next; std::function ret_func = nullptr; PIVector delims; PIConditionVariable event; }; #endif // PITIMER_H