version 4.0.0_alpha

in almost all methods removed timeouts in milliseconds, replaced to PISystemTime
PITimer rewrite, remove internal impl, now only thread implementation, API similar to PIThread
PITimer API no longer pass void*
PIPeer, PIConnection improved stability on reinit and exit
PISystemTime new methods
pisd now exit without hanging
This commit is contained in:
2024-07-30 14:18:02 +03:00
parent f07c9cbce8
commit 1c7fc39b6c
58 changed files with 677 additions and 1191 deletions

View File

@@ -26,50 +26,12 @@
#ifndef PITIMER_H
#define PITIMER_H
#include "pithread.h"
#include "pitime.h"
#include "piconditionvar.h"
#include "piobject.h"
#include "pisystemtime.h"
typedef std::function<void(void *, int)> TimerEvent;
class PITimer;
class PIP_EXPORT _PITimerBase {
friend class PITimer;
public:
_PITimerBase();
virtual ~_PITimerBase() {}
double interval() const { return interval_; }
void setInterval(double i);
bool isRunning() const { return running_; }
bool isStopped() const { return !running_; }
bool start() { return start(interval_); }
bool start(double interval_ms);
void startDeferred(double delay_ms) { startDeferred(interval_, delay_ms); }
void startDeferred(double interval_ms, double delay_ms);
void startDeferred(PIDateTime start_datetime) { startDeferred(interval_, start_datetime); }
void startDeferred(double interval_ms, PIDateTime start_datetime);
bool stop();
typedef void (*TickFunc)(PITimer *);
TickFunc tfunc = nullptr;
PITimer * parent = nullptr;
protected:
virtual bool startTimer(double interval_ms) = 0;
virtual bool stopTimer() = 0;
double interval_ = 1000., deferred_delay = 0.;
bool deferred_ = false, deferred_mode = false; // mode: true - date, false - delay
std::atomic_bool running_;
PIDateTime deferred_datetime;
};
class PIThread;
class PIP_EXPORT PITimer: public PIObject {
PIOBJECT_SUBCLASS(PITimer, PIObject);
@@ -77,118 +39,70 @@ class PIP_EXPORT PITimer: public PIObject {
public:
NO_COPY_CLASS(PITimer);
//! \~english Constructs timer with PITimer::Thread implementation
//! \~russian Создает таймер с реализацией PITimer::Thread
//! \~english Constructs timer
//! \~russian Создает таймер
explicit PITimer();
//! \~english Timer implementations
//! \~russian Реализация таймера
enum TimerImplementation {
Thread /*!
\~english Timer works in his own thread. Intervals are measured by the system time
\~russian Таймер работает в собственном потоке. Интервалы измеряются с помощью системного времени
*/
= 0x01,
ThreadRT /*!
\~english Using POSIX timer with SIGEV_THREAD notification. \attention Doesn`t support on Windows and Mac OS!
\~russian Использовать таймер POSIX с SIGEV_THREAD уведомлением. \attention Не поддерживается на Windows и Mac OS!
*/
= 0x02,
Pool /*!
\~english Using single TimerPool for all timers with this implementation. TimerPool works as Thread implementation and
sequentially executes all timers. \attention Use this implementation with care!
\~russian Использовать единый TimerPool для всех таймеров с этой реализацией. TimerPool реализован через Thread и
последовательно исполняет все таймеры. \attention Осторожнее с этой реализацией!
*/
= 0x04
};
//! \~english Constructs timer with method void(int)
//! \~russian Создает таймер с функцией void(int)
explicit PITimer(std::function<void(int)> func);
//! \~english Constructs timer with "ti" implementation
//! \~russian Создает таймер с реализацией "ti"
explicit PITimer(TimerImplementation ti);
//! \~english Constructs timer with "slot" slot void(void *,int), "data" data and "ti" implementation
//! \~russian Создает таймер со слотом "slot", данными "data" и реализацией "ti"
explicit PITimer(TimerEvent slot, void * data = 0, TimerImplementation ti = Thread);
//! \~english Constructs timer with "slot" slot void(), and "ti" implementation
//! \~russian Создает таймер со слотом "slot" и реализацией "ti"
explicit PITimer(std::function<void()> slot, TimerImplementation ti = Thread);
//! \~english Constructs timer with "slot" slot void(void *), "data" data and "ti" implementation
//! \~russian Создает таймер со слотом "slot", данными "data" и реализацией "ti"
explicit PITimer(std::function<void(void *)> slot, void * data, TimerImplementation ti = Thread);
//! \~english Constructs timer with method void()
//! \~russian Создает таймер с функцией void()
explicit PITimer(std::function<void()> func);
virtual ~PITimer();
//! \~english Returns timer loop delay
//! \~russian Возвращает задержку цикла таймера
PISystemTime interval() const;
//! \~english Returns timer implementation
//! \~russian Возвращает реализацию таймера
PITimer::TimerImplementation implementation() const { return imp_mode; }
//! \~english Returns timer loop delay in milliseconds
//! \~russian Возвращает задержку цикла таймера в миллисекундах
double interval() const;
EVENT_HANDLER1(void, setInterval, double, ms);
void setInterval(PISystemTime interval) { setInterval(interval.toMilliseconds()); }
//! \~english Set timer loop delay
//! \~russian Установить интервал таймера
void setInterval(PISystemTime interval);
//! \~english Returns if timer is started
//! \~russian Возвращает работает ли таймер
bool isRunning() const;
//! \~english Returns if timer is not started
//! \~russian Возвращает остановлен ли таймер
bool isStopped() const;
//! \~english Return if timer is stopping
//! \~russian Возвращает останавливается ли таймер
bool isStopping() const;
//! \~english Wait for timer stop
//! \~russian Ожидает остановки таймера
bool waitForFinish(PISystemTime timeout = {});
//! \fn bool start(PISystemTime interval)
//! \brief
//! \~english Start timer with "interval" loop delay
//! \~russian Запустить таймер с интервалом "interval"
bool start(PISystemTime interval);
bool start(double interval_ms) DEPRECATEDM("use start(PISystemTime)") { return start(PISystemTime::fromMilliseconds(interval_ms)); }
EVENT_HANDLER0(bool, start);
EVENT_HANDLER1(bool, start, double, interval_ms_d);
bool start(int interval_ms_i);
bool start(PISystemTime interval) { return start(interval.toMilliseconds()); }
EVENT_HANDLER0(bool, restart);
EVENT_HANDLER0(void, stop);
//! \~english Start timer with \a interval() loop delay after "delay_msecs" delay
//! \~russian Запускает таймер с интервалом \a interval() после ожидания "delay_msecs"
void startDeferred(double delay_ms);
//! \~english Stop timer and wait for finish.
//! \~russian Останавливает таймер и ожидает завершения.
void stopAndWait(int timeout_ms) { stopAndWait(PISystemTime::fromMilliseconds(timeout_ms)); }
//! \~english Start timer with "interval_msecs" loop delay after "delay_msecs" delay
//! \~russian Запускает таймер с интервалом "interval_msecs" после ожидания "delay_msecs"
void startDeferred(double interval_ms, double delay_ms);
//! \~english Start timer with \a interval() loop delay after "start_datetime" date and time
//! \~russian Запускает таймер с интервалом \a interval() после наступления "start_datetime"
void startDeferred(PIDateTime start_datetime);
//! \~english Start timer with "interval_msecs" loop delay after "start_datetime" date and time
//! \~russian Запускает таймер с интервалом "interval_msecs" после наступления "start_datetime"
void startDeferred(double interval_ms, PIDateTime start_datetime);
EVENT_HANDLER0(bool, stop);
//! \~english Set custom data
//! \~russian Установить данные, передаваемые в метод таймера
void setData(void * data_) { data_t = data_; }
//! \~english Returns common data passed to tick functions
//! \~russian Возвращает данные, передаваемые в метод таймера
void * data() const { return data_t; }
//! \~english Stop timer and wait for finish.
//! \~russian Останавливает таймер и ожидает завершения.
void stopAndWait(PISystemTime timeout = {});
//! \~english Set timer tick function
//! \~russian Установить вызываемый метод
void setSlot(TimerEvent slot) { ret_func = slot; }
//! \~english Set timer tick function
//! \~russian Установить вызываемый метод
void setSlot(std::function<void()> slot) {
ret_func = [slot](void *, int) { slot(); };
void setSlot(std::function<void()> func) {
ret_func = [func](int) { func(); };
}
//! \~english Set timer tick function
//! \~russian Установить вызываемый метод
void setSlot(std::function<void(void *)> slot) {
ret_func = [slot](void * d, int) { slot(d); };
}
void setSlot(std::function<void(int)> func) { ret_func = func; }
void needLockRun(bool need) { lockRun = need; }
EVENT_HANDLER0(void, lock) { mutex_.lock(); }
@@ -204,13 +118,11 @@ public:
//! \~english Add frequency delimiter "delim" with optional delimiter slot "slot"
//! \~russian Добавляет делитель частоты "delim" с необязательным методом "slot"
void addDelimiter(int delim, TimerEvent slot = 0) { delims << Delimiter(slot, delim); }
void addDelimiter(int delim, std::function<void(int)> func = nullptr);
//! \~english Add frequency delimiter "delim" with optional delimiter slot "slot"
//! \~russian Добавляет делитель частоты "delim" с необязательным методом "slot"
void addDelimiter(int delim, std::function<void()> slot) {
delims << Delimiter([slot](void *, int) { slot(); }, delim);
}
void addDelimiter(int delim, std::function<void()> func);
//! \~english Add frequency delimiter "delim" with optional delimiter slot "slot"
//! \~russian Добавляет делитель частоты "delim" с необязательным методом "slot"
@@ -222,39 +134,15 @@ public:
EVENT_HANDLER0(void, clearDelimiters) { delims.clear(); }
EVENT2(tickEvent, void *, data_, int, delimiter);
EVENT1(tickEvent, int, delimiter);
//! \handlers
//! \{
//! \fn void setInterval(double ms)
//! \brief
//! \~english Set timer loop delay in milliseconds
//! \~russian Установить интервал таймера "ms" миллисекунд
//! \fn bool start()
//! \brief
//! \~english Start timer with \a interval() loop delay
//! \~russian Запустить таймер с интервалом \a interval()
//! \~\details
//! \~english
//! Start execution of timer functions with frequency = 1 / msecs Hz
//! \~russian
//! Запускает таймер с частотой = 1 / msecs Гц
//! \fn bool start(double msecs)
//! \brief
//! \~english Start timer with "msecs" loop delay
//! \~russian Запустить таймер с интервалом "msecs"
//! \~\details
//! \~english
//! Start execution of timer functions with frequency = 1. / msecs Hz.
//! Instead of \a start(int msecs) this function allow start timer
//! with frequencies more than 1 kHz
//! \~russian
//! Запускает таймер с частотой = 1 / msecs Гц. В отличии от
//! \a start(int msecs) этот метод позволяет запустить таймер с частотой
//! более 1 кГц
//! \fn bool restart()
//! \brief
@@ -263,8 +151,8 @@ public:
//! \fn bool stop()
//! \brief
//! \~english Stop timer and wait for it finish
//! \~russian Остановить таймер и дождаться остановки
//! \~english Stop timer (don`t wait for finish)
//! \~russian Остановить таймер (не дожидается остановки)
//! \fn void clearDelimiters()
//! \brief
@@ -275,16 +163,14 @@ public:
//! \events
//! \{
//! \fn void tickEvent(void * data, int delimiter)
//! \fn void tickEvent(int delimiter)
//! \brief
//! \~english Raise on timer tick
//! \~russian Вызывается каждый тик таймера
//! \~\details
//! \~english
//! "data" can be set with function \a setData() or from constructor.
//! "delimiter" is frequency delimiter, 1 for main loop.
//! \~russian
//! "data" устанавливается методом \a setData() или в конструкторе.
//! "delimiter" - делитель частоты, 1 для основного цикла
@@ -292,33 +178,33 @@ public:
protected:
struct PIP_EXPORT Delimiter {
Delimiter(TimerEvent slot_ = 0, int delim_ = 1) {
slot = slot_;
Delimiter(std::function<void(int)> func_ = nullptr, int delim_ = 1) {
func = func_;
delim = delim_;
}
TimerEvent slot;
std::function<void(int)> func;
int delim = 0;
int tick = 0;
};
void initFirst();
void init() const;
void destroy();
static void tickImpS(PITimer * t) { t->tickImp(); }
void tickImp();
void threadFunc();
void adjustTimes();
void execTick();
//! Timer execution function, similar to "slot" or event \a timeout(). By default does nothing
virtual void tick(void * data_, int delimiter) {}
virtual void tick(int delimiter) {}
void * data_t = nullptr;
std::atomic_bool lockRun, callEvents;
PIThread * thread = nullptr;
std::atomic_bool lockRun = {false}, callEvents = {true};
PIMutex mutex_;
TimerEvent ret_func = nullptr;
TimerImplementation imp_mode = Thread;
PISystemTime m_interval, m_interval_x5;
PISystemTime m_time_next;
std::function<void(int)> ret_func = nullptr;
PIVector<Delimiter> delims;
mutable _PITimerBase * imp = nullptr;
PIConditionVariable event;
};