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:
@@ -20,11 +20,8 @@
|
||||
#include "pitimer.h"
|
||||
|
||||
#include "piconditionvar.h"
|
||||
#include "piincludes_p.h"
|
||||
#include "piliterals.h"
|
||||
#ifdef PIP_TIMER_RT
|
||||
# include <csignal>
|
||||
#endif
|
||||
#include "piliterals_time.h"
|
||||
#include "pithread.h"
|
||||
|
||||
|
||||
//! \addtogroup Thread
|
||||
@@ -52,22 +49,22 @@
|
||||
//! \~russian \section PITimer_sec1 Варианты уведомления
|
||||
//! \~english
|
||||
//! Notify variants:
|
||||
//! * "slot" - static function with format void func(void * data, int delimiter) or [lambda
|
||||
//! * "slot" - static function with format void func(int delimiter) or [lambda
|
||||
//! expression](https://en.cppreference.com/w/cpp/language/lambda);
|
||||
//! * event - \a tickEvent();
|
||||
//! * virtual function - \a tick().
|
||||
//!
|
||||
//! Lambda should be [ ]( ){ } or [ ](void*){ } format.
|
||||
//! Lambda should be [ ]( ){ } or [ ](int){ } format.
|
||||
//!
|
||||
//! All these variants are equivalent, use most applicable.
|
||||
//! \~russian
|
||||
//! Варианты уведомления:
|
||||
//! * "slot" - статический метод в формате void func(void * data, int delimiter) или
|
||||
//! * "slot" - статический метод в формате void func(int delimiter) или
|
||||
//! [лямбда-выражение](https://ru.cppreference.com/w/cpp/language/lambda);
|
||||
//! * event - \a tickEvent();
|
||||
//! * виртуальный метод - \a tick().
|
||||
//!
|
||||
//! Лямбда-функция должна быть в формате [ ]( ){ } или [ ](void*){ }.
|
||||
//! Лямбда-функция должна быть в формате [ ]( ){ } или [ ](int){ }.
|
||||
//!
|
||||
//! Все варианты аналогичны друг другу, используйте самый удобный.
|
||||
//!
|
||||
@@ -89,10 +86,10 @@
|
||||
//! Пример:
|
||||
//!
|
||||
//! \~\code
|
||||
//! void tfunc(void * , int delim) {
|
||||
//! void tfunc(int delim) {
|
||||
//! piCout << "tick with delimiter" << delim;
|
||||
//! };
|
||||
//! void tfunc4(void * , int delim) {
|
||||
//! void tfunc4(int delim) {
|
||||
//! piCout << "tick4 with delimiter" << delim;
|
||||
//! };
|
||||
//! int main() {
|
||||
@@ -101,8 +98,7 @@
|
||||
//! timer.addDelimiter(4, tfunc4);
|
||||
//! timer.start(50);
|
||||
//! piMSleep(200);
|
||||
//! timer.stop();
|
||||
//! timer.waitForFinish();
|
||||
//! timer.stopAndWait();
|
||||
//! return 0;
|
||||
//! };
|
||||
//! /* Result:
|
||||
@@ -119,596 +115,163 @@
|
||||
//! \}
|
||||
|
||||
|
||||
_PITimerBase::_PITimerBase() {
|
||||
running_ = false;
|
||||
PITimer::PITimer(): PIObject() {
|
||||
initFirst();
|
||||
}
|
||||
|
||||
|
||||
void _PITimerBase::setInterval(double i) {
|
||||
interval_ = i;
|
||||
PITimer::PITimer(std::function<void(int)> func) {
|
||||
initFirst();
|
||||
ret_func = func;
|
||||
}
|
||||
|
||||
|
||||
PITimer::PITimer(std::function<void()> func) {
|
||||
initFirst();
|
||||
ret_func = [func](int) { func(); };
|
||||
}
|
||||
|
||||
|
||||
PITimer::~PITimer() {
|
||||
stopAndWait();
|
||||
piDeleteSafety(thread);
|
||||
}
|
||||
|
||||
|
||||
PISystemTime PITimer::interval() const {
|
||||
return m_interval;
|
||||
}
|
||||
|
||||
|
||||
void PITimer::setInterval(PISystemTime interval) {
|
||||
if (m_interval == interval) return;
|
||||
m_interval = interval;
|
||||
if (isRunning()) {
|
||||
// piCout << "change interval runtime";
|
||||
stop();
|
||||
stopAndWait();
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool _PITimerBase::start(double interval_ms) {
|
||||
if (isRunning()) stop();
|
||||
deferred_ = false;
|
||||
setInterval(interval_ms);
|
||||
// piCout << "_PITimerBase::startTimer"<<interval_ms<<"...";
|
||||
running_ = startTimer(interval_ms);
|
||||
return running_;
|
||||
}
|
||||
|
||||
|
||||
void _PITimerBase::startDeferred(double interval_ms, PIDateTime start_datetime) {
|
||||
if (isRunning()) stop();
|
||||
deferred_ = true;
|
||||
deferred_mode = true;
|
||||
deferred_datetime = start_datetime;
|
||||
setInterval(interval_ms);
|
||||
running_ = startTimer(interval_ms);
|
||||
}
|
||||
|
||||
|
||||
void _PITimerBase::startDeferred(double interval_ms, double delay_ms) {
|
||||
if (isRunning()) stop();
|
||||
deferred_ = true;
|
||||
deferred_mode = false;
|
||||
deferred_delay = delay_ms;
|
||||
setInterval(interval_ms);
|
||||
running_ = startTimer(interval_ms);
|
||||
}
|
||||
|
||||
|
||||
bool _PITimerBase::stop() {
|
||||
// piCout << GetCurrentThreadId() << "_PITimerBase::stop" << wait << isRunning();
|
||||
if (!isRunning()) return true;
|
||||
// piCout << "_PITimerBase::stopTimer ...";
|
||||
running_ = !stopTimer();
|
||||
return !running_;
|
||||
}
|
||||
|
||||
|
||||
class _PITimerImp_Thread: public _PITimerBase {
|
||||
public:
|
||||
_PITimerImp_Thread();
|
||||
virtual ~_PITimerImp_Thread() { stop(); }
|
||||
|
||||
protected:
|
||||
void prepareStart(double interval_ms);
|
||||
bool threadFunc(); // returns true if repeat is needed
|
||||
int wait_dt, wait_dd, wait_tick;
|
||||
|
||||
private:
|
||||
bool startTimer(double interval_ms) override;
|
||||
bool stopTimer() override;
|
||||
static void threadFuncS(void * d) { ((_PITimerImp_Thread *)d)->threadFunc(); }
|
||||
void adjustTimes();
|
||||
bool smallWait(int ms);
|
||||
|
||||
PIThread thread_;
|
||||
PISystemTime st_time, st_inc, st_wait, st_odt;
|
||||
PIConditionVariable event;
|
||||
};
|
||||
|
||||
|
||||
#ifdef PIP_TIMER_RT
|
||||
struct _PITimerImp_RT_Private_;
|
||||
class _PITimerImp_RT: public _PITimerBase {
|
||||
public:
|
||||
_PITimerImp_RT();
|
||||
virtual ~_PITimerImp_RT();
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
bool startTimer(double interval_ms) override;
|
||||
bool stopTimer() override;
|
||||
|
||||
int ti;
|
||||
_PITimerImp_RT_Private_ * priv;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
class _PITimerImp_Pool: public _PITimerImp_Thread {
|
||||
public:
|
||||
_PITimerImp_Pool();
|
||||
virtual ~_PITimerImp_Pool() { stop(); }
|
||||
|
||||
private:
|
||||
class Pool: public PIThread {
|
||||
public:
|
||||
static Pool * instance();
|
||||
void add(_PITimerImp_Pool * t);
|
||||
void remove(_PITimerImp_Pool * t);
|
||||
void run() override;
|
||||
PIVector<_PITimerImp_Pool *> timers, to_remove;
|
||||
|
||||
private:
|
||||
explicit Pool();
|
||||
virtual ~Pool();
|
||||
};
|
||||
bool startTimer(double interval_ms) override;
|
||||
bool stopTimer() override;
|
||||
};
|
||||
|
||||
|
||||
_PITimerImp_Thread::_PITimerImp_Thread() {
|
||||
thread_.setName("__S__PITimerImp_Thread::thread"_a);
|
||||
wait_dt = 1000;
|
||||
wait_dd = 2000;
|
||||
wait_tick = 1000;
|
||||
// piCout << "_PITimerImp_Thread" << this << ", thread& =" << &thread_;
|
||||
// piCout << "new _PITimerImp_Thread";
|
||||
}
|
||||
|
||||
|
||||
void _PITimerImp_Thread::prepareStart(double interval_ms) {
|
||||
if (interval_ms <= 0.) {
|
||||
piCout << "Achtung! Start PITimer with interval <= 0!";
|
||||
piCout << "Achtung! Parent" << parent;
|
||||
assert(interval_ms > 0.);
|
||||
}
|
||||
st_inc = PISystemTime::fromMilliseconds(interval_ms);
|
||||
st_odt = st_inc * 5;
|
||||
if (st_odt.toSeconds() < 1.) st_odt = 1_s;
|
||||
if (deferred_) {
|
||||
if (!deferred_mode) st_time = PISystemTime::current(true) + PISystemTime::fromMilliseconds(deferred_delay);
|
||||
st_time -= st_inc;
|
||||
} else
|
||||
st_time = PISystemTime::current(true) + st_inc;
|
||||
}
|
||||
|
||||
|
||||
bool _PITimerImp_Thread::startTimer(double interval_ms) {
|
||||
prepareStart(interval_ms);
|
||||
thread_.setData(this);
|
||||
return thread_.start(threadFuncS);
|
||||
}
|
||||
|
||||
|
||||
bool _PITimerImp_Thread::stopTimer() {
|
||||
thread_.stop();
|
||||
event.notifyAll();
|
||||
thread_.waitForFinish();
|
||||
// if (wait)
|
||||
// if (!thread_.waitForFinish(10))
|
||||
// if (thread_.isRunning())
|
||||
// thread_.terminate();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool _PITimerImp_Thread::threadFunc() {
|
||||
if (!running_) return false;
|
||||
if (deferred_) {
|
||||
PISystemTime dwt;
|
||||
int wth(wait_dt);
|
||||
if (deferred_mode) {
|
||||
dwt = deferred_datetime.toSystemTime() - PISystemTime::current();
|
||||
wth = wait_dd;
|
||||
} else
|
||||
dwt = st_time - PISystemTime::current(true);
|
||||
if (wth > 0) {
|
||||
if (dwt.toMilliseconds() > wth + 1.) {
|
||||
smallWait(wth);
|
||||
return false;
|
||||
} else {
|
||||
if (!smallWait(dwt.toMilliseconds())) return false;
|
||||
deferred_ = false;
|
||||
st_time = PISystemTime::current(true);
|
||||
}
|
||||
} else {
|
||||
if (dwt.toMilliseconds() > 0.1) return false;
|
||||
}
|
||||
}
|
||||
st_wait = st_time - PISystemTime::current(true);
|
||||
// piCout << "wait" << this << st_wait;
|
||||
if (st_wait.abs() > st_odt || st_wait.seconds <= -5) {
|
||||
// piCout << &thread_ << "adjust" << "...";
|
||||
adjustTimes();
|
||||
// piCout << &thread_ << "adjust" << "ok";
|
||||
return true;
|
||||
}
|
||||
if (wait_tick > 0) {
|
||||
if (st_wait.toMilliseconds() > wait_tick + 1.) {
|
||||
smallWait(wait_tick);
|
||||
return false;
|
||||
} else {
|
||||
// piCout << &thread_ << "sleep for" << st_wait;
|
||||
if (!smallWait(st_wait.toMilliseconds())) return false;
|
||||
}
|
||||
} else {
|
||||
if (st_wait.toMilliseconds() > 0.1) return false;
|
||||
}
|
||||
st_time += st_inc;
|
||||
if (!parent->isPIObject()) {
|
||||
piCout << "Achtung! PITimer \"parent\" is not PIObject!";
|
||||
return false;
|
||||
}
|
||||
// piCout << &thread_ << "tfunc" << "...";
|
||||
tfunc(parent);
|
||||
// piCout << &thread_ << "tfunc" << "ok";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void _PITimerImp_Thread::adjustTimes() {
|
||||
PISystemTime cst = PISystemTime::current(true);
|
||||
if (st_time < cst) {
|
||||
int rs = (cst - st_time).toSeconds() / st_inc.toSeconds();
|
||||
if (rs >= 100)
|
||||
st_time = cst + st_inc;
|
||||
else {
|
||||
while (st_time < cst)
|
||||
st_time += st_inc;
|
||||
}
|
||||
} else {
|
||||
int rs = (st_time - cst).toSeconds() / st_inc.toSeconds();
|
||||
if (rs >= 100)
|
||||
st_time = cst - st_inc;
|
||||
else {
|
||||
cst += st_inc;
|
||||
while (st_time > cst)
|
||||
st_time -= st_inc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool _PITimerImp_Thread::smallWait(int ms) {
|
||||
if (thread_.isStopping()) return false;
|
||||
if (ms > 0) {
|
||||
thread_.mutex().lock();
|
||||
event.waitFor(thread_.mutex(), ms);
|
||||
thread_.mutex().unlock();
|
||||
}
|
||||
return !thread_.isStopping();
|
||||
}
|
||||
|
||||
|
||||
#ifdef PIP_TIMER_RT
|
||||
|
||||
void threadFuncS(sigval sv) {
|
||||
((_PITimerImp_RT *)sv.sival_ptr)->tfunc(((_PITimerImp_RT *)sv.sival_ptr)->parent);
|
||||
}
|
||||
|
||||
struct _PITimerImp_RT_Private_ {
|
||||
itimerspec spec;
|
||||
timer_t tt;
|
||||
sigevent se;
|
||||
};
|
||||
|
||||
_PITimerImp_RT::_PITimerImp_RT() {
|
||||
// piCout << "new _PITimerImp_RT";
|
||||
priv = new _PITimerImp_RT_Private_();
|
||||
priv->tt = 0;
|
||||
ti = -1;
|
||||
memset(&(priv->se), 0, sizeof(priv->se));
|
||||
priv->se.sigev_notify = SIGEV_THREAD;
|
||||
priv->se.sigev_value.sival_ptr = this;
|
||||
priv->se.sigev_notify_function = threadFuncS;
|
||||
priv->se.sigev_notify_attributes = 0;
|
||||
}
|
||||
|
||||
|
||||
_PITimerImp_RT::~_PITimerImp_RT() {
|
||||
stop();
|
||||
delete priv;
|
||||
}
|
||||
|
||||
|
||||
bool _PITimerImp_RT::startTimer(double interval_ms) {
|
||||
int flags(0);
|
||||
priv->spec.it_interval.tv_nsec = ((int)(interval_ms * 1000) % 1000000) * 1000;
|
||||
priv->spec.it_interval.tv_sec = (time_t)(interval_ms / 1000);
|
||||
if (deferred_) {
|
||||
if (deferred_mode) {
|
||||
PISystemTime dtm = deferred_datetime.toSystemTime();
|
||||
priv->spec.it_value.tv_nsec = dtm.nanoseconds;
|
||||
priv->spec.it_value.tv_sec = dtm.seconds;
|
||||
flags = TIMER_ABSTIME;
|
||||
} else {
|
||||
priv->spec.it_value.tv_nsec = ((int)(deferred_delay * 1000) % 1000000) * 1000;
|
||||
priv->spec.it_value.tv_sec = (time_t)(deferred_delay / 1000);
|
||||
}
|
||||
} else {
|
||||
priv->spec.it_value = priv->spec.it_interval;
|
||||
}
|
||||
ti = timer_create(CLOCK_REALTIME, &(priv->se), &(priv->tt));
|
||||
// cout << "***create timer " << msecs << " msecs\n";
|
||||
if (ti == -1) {
|
||||
piCout << "Can`t create RT timer for " << interval_ms << " msecs: " << errorString();
|
||||
return false;
|
||||
}
|
||||
timer_settime(priv->tt, flags, &(priv->spec), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool _PITimerImp_RT::stopTimer() {
|
||||
if (ti < 0) return true;
|
||||
timer_delete(priv->tt);
|
||||
ti = -1;
|
||||
priv->tt = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
_PITimerImp_Pool::_PITimerImp_Pool(): _PITimerImp_Thread() {
|
||||
wait_dt = wait_dd = wait_tick = 0;
|
||||
// piCout << "new _PITimerImp_Pool";
|
||||
}
|
||||
|
||||
|
||||
_PITimerImp_Pool::Pool::Pool(): PIThread() {
|
||||
setName("__S__PITimerImp_Pool::Pool"_a);
|
||||
needLockRun(true);
|
||||
#ifndef FREERTOS
|
||||
timers.reserve(64);
|
||||
start(PIP_MIN_MSLEEP * 5);
|
||||
#else
|
||||
start(PIP_MIN_MSLEEP);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
_PITimerImp_Pool::Pool::~Pool() {
|
||||
stop();
|
||||
if (!waitForFinish(500)) terminate();
|
||||
unlock();
|
||||
timers.clear();
|
||||
}
|
||||
|
||||
|
||||
_PITimerImp_Pool::Pool * _PITimerImp_Pool::Pool::instance() {
|
||||
static Pool pool;
|
||||
return &pool;
|
||||
}
|
||||
|
||||
|
||||
void _PITimerImp_Pool::Pool::add(_PITimerImp_Pool * t) {
|
||||
// piCout << "add ...";
|
||||
lock();
|
||||
to_remove.removeAll(t);
|
||||
if (!timers.contains(t)) timers << t;
|
||||
unlock();
|
||||
// piCout << "add done";
|
||||
}
|
||||
|
||||
|
||||
void _PITimerImp_Pool::Pool::remove(_PITimerImp_Pool * t) {
|
||||
// piCout << "remove ...";
|
||||
lock();
|
||||
to_remove << t;
|
||||
unlock();
|
||||
// piCout << "remove done";
|
||||
}
|
||||
|
||||
|
||||
void _PITimerImp_Pool::Pool::run() {
|
||||
if (!to_remove.isEmpty()) {
|
||||
piForeach(_PITimerImp_Pool * t, to_remove)
|
||||
timers.removeAll(t);
|
||||
to_remove.clear();
|
||||
}
|
||||
piForeach(_PITimerImp_Pool * t, timers)
|
||||
t->threadFunc();
|
||||
}
|
||||
|
||||
|
||||
bool _PITimerImp_Pool::startTimer(double interval_ms) {
|
||||
prepareStart(interval_ms);
|
||||
Pool::instance()->add(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool _PITimerImp_Pool::stopTimer() {
|
||||
Pool::instance()->remove(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
PITimer::PITimer(): PIObject() {
|
||||
#ifdef FREERTOS
|
||||
imp_mode = PITimer::Thread;
|
||||
#else
|
||||
imp_mode = PITimer::Thread;
|
||||
#endif
|
||||
initFirst();
|
||||
}
|
||||
|
||||
|
||||
PITimer::PITimer(PITimer::TimerImplementation ti): PIObject() {
|
||||
imp_mode = ti;
|
||||
initFirst();
|
||||
}
|
||||
|
||||
|
||||
PITimer::PITimer(TimerEvent slot, void * data, PITimer::TimerImplementation ti): PIObject() {
|
||||
imp_mode = ti;
|
||||
initFirst();
|
||||
data_t = data;
|
||||
ret_func = slot;
|
||||
}
|
||||
|
||||
|
||||
PITimer::PITimer(std::function<void()> slot, PITimer::TimerImplementation ti) {
|
||||
imp_mode = ti;
|
||||
initFirst();
|
||||
ret_func = [slot](void *, int) { slot(); };
|
||||
}
|
||||
|
||||
|
||||
PITimer::PITimer(std::function<void(void *)> slot, void * data, PITimer::TimerImplementation ti) {
|
||||
imp_mode = ti;
|
||||
initFirst();
|
||||
data_t = data;
|
||||
ret_func = [slot](void * d, int) { slot(d); };
|
||||
}
|
||||
|
||||
|
||||
PITimer::~PITimer() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
|
||||
double PITimer::interval() const {
|
||||
init();
|
||||
return imp->interval_;
|
||||
}
|
||||
|
||||
|
||||
void PITimer::setInterval(double ms) {
|
||||
init();
|
||||
setProperty("interval", ms);
|
||||
imp->setInterval(ms);
|
||||
}
|
||||
|
||||
|
||||
bool PITimer::isRunning() const {
|
||||
init();
|
||||
return imp->running_;
|
||||
return thread->isRunning();
|
||||
}
|
||||
|
||||
|
||||
bool PITimer::isStopped() const {
|
||||
init();
|
||||
return !imp->running_;
|
||||
bool PITimer::isStopping() const {
|
||||
return thread->isStopping();
|
||||
}
|
||||
|
||||
|
||||
bool PITimer::waitForFinish(PISystemTime timeout) {
|
||||
return thread->waitForFinish(timeout);
|
||||
}
|
||||
|
||||
|
||||
void PITimer::initFirst() {
|
||||
lockRun = false;
|
||||
callEvents = true;
|
||||
setProperty("interval", 0.);
|
||||
thread = new PIThread([this] { threadFunc(); });
|
||||
thread->setName("__S__.PITimer.thread");
|
||||
setProperty("interval", PISystemTime());
|
||||
}
|
||||
|
||||
|
||||
void PITimer::init() const {
|
||||
if (imp) return;
|
||||
switch (imp_mode) {
|
||||
case PITimer::Pool: imp = new _PITimerImp_Pool(); break;
|
||||
case PITimer::ThreadRT:
|
||||
#ifdef PIP_TIMER_RT
|
||||
imp = new _PITimerImp_RT();
|
||||
break;
|
||||
#else
|
||||
piCoutObj << "Warning: \"ThreadRT\" is not available at this system! Using \"Thread\".";
|
||||
#endif
|
||||
case PITimer::Thread: imp = new _PITimerImp_Thread(); break;
|
||||
default: piCout << "Fatal: invalid implementation() of" << this << "!"; assert(0);
|
||||
void PITimer::threadFunc() {
|
||||
PISystemTime st_wait = m_time_next - PISystemTime::current(true);
|
||||
// piCout << "wait" << this << st_wait;
|
||||
if (st_wait.abs() > m_interval_x5 || st_wait.seconds <= -5) {
|
||||
// piCout << &thread_ << "adjust" << "...";
|
||||
adjustTimes();
|
||||
// piCout << &thread_ << "adjust" << "ok";
|
||||
return;
|
||||
}
|
||||
if (!imp) return;
|
||||
// piCout << this << "init" << imp;
|
||||
imp->tfunc = tickImpS;
|
||||
imp->parent = const_cast<PITimer *>(this);
|
||||
if (thread->isStopping()) return;
|
||||
if (st_wait.isPositive()) {
|
||||
thread->mutex().lock();
|
||||
event.waitFor(thread->mutex(), st_wait);
|
||||
thread->mutex().unlock();
|
||||
}
|
||||
if (thread->isStopping()) return;
|
||||
m_time_next += m_interval;
|
||||
// piCout << &thread_ << "tfunc" << "...";
|
||||
execTick();
|
||||
}
|
||||
|
||||
|
||||
void PITimer::destroy() {
|
||||
if (!imp) return;
|
||||
// piCout << this << "destroy" << imp;
|
||||
imp->stop();
|
||||
delete imp;
|
||||
imp = 0;
|
||||
void PITimer::adjustTimes() {
|
||||
PISystemTime cst = PISystemTime::current(true);
|
||||
if (m_time_next < cst) {
|
||||
int rs = (cst - m_time_next).toSeconds() / m_interval.toSeconds();
|
||||
if (rs >= 100)
|
||||
m_time_next = cst + m_interval;
|
||||
else {
|
||||
while (m_time_next < cst)
|
||||
m_time_next += m_interval;
|
||||
}
|
||||
} else {
|
||||
int rs = (m_time_next - cst).toSeconds() / m_interval.toSeconds();
|
||||
if (rs >= 100)
|
||||
m_time_next = cst - m_interval;
|
||||
else {
|
||||
cst += m_interval;
|
||||
while (m_time_next > cst)
|
||||
m_time_next -= m_interval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PITimer::tickImp() {
|
||||
void PITimer::execTick() {
|
||||
if (!isRunning()) return;
|
||||
if (lockRun) lock();
|
||||
if (ret_func) ret_func(data_t, 1);
|
||||
tick(data_t, 1);
|
||||
tickEvent(data_t, 1);
|
||||
if (ret_func) ret_func(1);
|
||||
tick(1);
|
||||
tickEvent(1);
|
||||
if (callEvents) maybeCallQueuedEvents();
|
||||
piForeach(Delimiter & i, delims) {
|
||||
for (Delimiter & i: delims) {
|
||||
if (i.delim > ++(i.tick)) continue;
|
||||
i.tick = 0;
|
||||
if (i.slot)
|
||||
i.slot(data_t, i.delim);
|
||||
if (i.func)
|
||||
i.func(i.delim);
|
||||
else if (ret_func)
|
||||
ret_func(data_t, i.delim);
|
||||
tick(data_t, i.delim);
|
||||
tickEvent(data_t, i.delim);
|
||||
ret_func(i.delim);
|
||||
tick(i.delim);
|
||||
tickEvent(i.delim);
|
||||
}
|
||||
if (lockRun) unlock();
|
||||
}
|
||||
|
||||
|
||||
bool PITimer::start() {
|
||||
init();
|
||||
// piCout << this << "start" << imp;
|
||||
return imp->start();
|
||||
if (isRunning()) return true;
|
||||
m_interval_x5 = m_interval * 5;
|
||||
if (m_interval_x5.toSeconds() < 1.) m_interval_x5 = 1_s;
|
||||
m_time_next = PISystemTime::current(true) + m_interval;
|
||||
if (!thread->start()) return false;
|
||||
return thread->waitForStart();
|
||||
}
|
||||
|
||||
|
||||
bool PITimer::start(double interval_ms_d) {
|
||||
init();
|
||||
// piCout << this << "start" << imp << interval_ms_d;
|
||||
setProperty("interval", interval_ms_d);
|
||||
return imp->start(interval_ms_d);
|
||||
bool PITimer::start(PISystemTime interval) {
|
||||
if (isRunning()) stopAndWait();
|
||||
setInterval(interval);
|
||||
return start();
|
||||
}
|
||||
|
||||
|
||||
bool PITimer::start(int interval_ms_i) {
|
||||
return start((double)interval_ms_i);
|
||||
void PITimer::stopAndWait(PISystemTime timeout) {
|
||||
stop();
|
||||
thread->waitForFinish(timeout);
|
||||
}
|
||||
|
||||
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! Timer wait "delay_msecs" milliseconds and then normally starts with \a interval() loop delay
|
||||
//! \~russian
|
||||
//! Таймер ожидает "delay_msecs" миллисекунд, а затем стартует с интервалом \a interval()
|
||||
void PITimer::startDeferred(double delay_ms) {
|
||||
init();
|
||||
imp->startDeferred(delay_ms);
|
||||
void PITimer::addDelimiter(int delim, std::function<void(int)> func) {
|
||||
delims << Delimiter(func, delim);
|
||||
}
|
||||
|
||||
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! Timer wait "delay_msecs" milliseconds and then normally starts with "interval_msecs" loop delay
|
||||
//! \~russian
|
||||
//! Таймер ожидает "delay_msecs" миллисекунд, а затем стартует с интервалом "interval_msecs"
|
||||
void PITimer::startDeferred(double interval_ms, double delay_ms) {
|
||||
init();
|
||||
imp->startDeferred(interval_ms, delay_ms);
|
||||
}
|
||||
|
||||
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! Timer wait until "start_datetime" and then normally starts with \a interval() loop delay
|
||||
//! \~russian
|
||||
//! Таймер ожидает наступления "start_datetime", а затем стартует с интервалом \a interval()
|
||||
void PITimer::startDeferred(PIDateTime start_datetime) {
|
||||
startDeferred(imp->interval_, start_datetime);
|
||||
}
|
||||
|
||||
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! Timer wait until "start_datetime" and then normally starts with "interval_msecs" loop delay
|
||||
//! \~russian
|
||||
//! Таймер ожидает наступления "start_datetime", а затем стартует с интервалом "interval_msecs"
|
||||
void PITimer::startDeferred(double interval_ms, PIDateTime start_datetime) {
|
||||
init();
|
||||
imp->startDeferred(interval_ms, start_datetime);
|
||||
}
|
||||
|
||||
|
||||
void PITimer::addDelimiter(int delim, std::function<void(void *)> slot) {
|
||||
delims << Delimiter([slot](void * d, int) { slot(d); }, delim);
|
||||
void PITimer::addDelimiter(int delim, std::function<void()> func) {
|
||||
delims << Delimiter([func](int) { func(); }, delim);
|
||||
}
|
||||
|
||||
|
||||
@@ -722,14 +285,12 @@ void PITimer::removeDelimiter(int delim) {
|
||||
|
||||
|
||||
bool PITimer::restart() {
|
||||
init();
|
||||
imp->stop();
|
||||
return imp->start();
|
||||
stopAndWait();
|
||||
return start();
|
||||
}
|
||||
|
||||
|
||||
bool PITimer::stop() {
|
||||
init();
|
||||
// piCout << this << "stop" << imp << wait;
|
||||
return imp->stop();
|
||||
void PITimer::stop() {
|
||||
thread->stop();
|
||||
event.notifyAll();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user