212 lines
5.3 KiB
C++
212 lines
5.3 KiB
C++
/*
|
|
PIP - Platform Independent Primitives
|
|
Timer
|
|
Copyright (C) 2011 Ivan Pelipenko peri4@rambler.ru
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "pitimer.h"
|
|
|
|
|
|
PITimer::PITimer(TimerEvent slot, void * data_)
|
|
#ifdef WINDOWS
|
|
: PIThread() {
|
|
#else
|
|
: PIObject() {
|
|
#endif
|
|
ret_func = slot;
|
|
data = data_;
|
|
#ifndef WINDOWS
|
|
piMonitor.timers++;
|
|
ti = -1;
|
|
running = false;
|
|
se.sigev_notify = SIGEV_THREAD;
|
|
se.sigev_value.sival_ptr = this;
|
|
se.sigev_notify_function = timer_event;
|
|
se.sigev_notify_attributes = 0;
|
|
lockRun = false;
|
|
#endif
|
|
reset();
|
|
/*addEvent<void*, int>("timeout");
|
|
addEventHandler<double>(HANDLER(PITimer, start));
|
|
addEventHandler(HANDLER(PITimer, stop));
|
|
addEventHandler(HANDLER(PITimer, reset));*/
|
|
}
|
|
|
|
|
|
PITimer::~PITimer() {
|
|
#ifndef WINDOWS
|
|
piMonitor.timers--;
|
|
#endif
|
|
stop();
|
|
}
|
|
|
|
|
|
#ifndef WINDOWS
|
|
void PITimer::start(double msecs) {
|
|
if (ti == 0) return;
|
|
spec.it_interval.tv_nsec = ((int)(msecs * 1000) % 1000000) * 1000;
|
|
spec.it_interval.tv_sec = (time_t)(msecs / 1000);
|
|
spec.it_value = spec.it_interval;
|
|
ti = timer_create(CLOCK_REALTIME, &se, &timer);
|
|
timer_settime(timer, 0, &spec, 0);
|
|
running = true;
|
|
}
|
|
|
|
|
|
void PITimer::timer_event(sigval e) {
|
|
PITimer * ct = (PITimer * )e.sival_ptr;
|
|
if (!ct->running) return;
|
|
if (ct->lockRun) ct->lock();
|
|
if (ct->ret_func != 0) ct->ret_func(ct->data, 1);
|
|
raiseEvent<void*, int>(ct, "timeout", ct->data, 1);
|
|
piForeach (TimerSlot & i, ct->ret_funcs) {
|
|
if (i.delim > ++(i.tick)) continue;
|
|
i.tick = 0;
|
|
if (i.slot != 0) i.slot(ct->data, i.delim);
|
|
else if (ct->ret_func != 0) ct->ret_func(ct->data, i.delim);
|
|
raiseEvent<void*, int>(ct, "timeout", ct->data, i.delim);
|
|
}
|
|
if (ct->lockRun) ct->unlock();
|
|
}
|
|
|
|
|
|
bool PITimer::waitForFinish(int timeout_msecs) {
|
|
if (timeout_msecs < 0) {
|
|
while (running)
|
|
msleep(1);
|
|
return true;
|
|
}
|
|
int cnt = 0;
|
|
while (running && cnt < timeout_msecs) {
|
|
msleep(1);
|
|
++cnt;
|
|
}
|
|
return cnt < timeout_msecs;
|
|
}
|
|
|
|
|
|
#else
|
|
void PITimer::run() {
|
|
if (!running) return;
|
|
if (lockRun) lock();
|
|
if (ret_func != 0) ret_func(data, 1);
|
|
raiseEvent<void*, int>(this, "timeout", data, 1);
|
|
piForeach (TimerSlot & i, ret_funcs) {
|
|
if (i.delim > ++(i.tick)) continue;
|
|
i.tick = 0;
|
|
if (i.slot != 0) i.slot(data, i.delim);
|
|
else if (ret_func != 0) ret_func(data, i.delim);
|
|
raiseEvent<void*, int>(this, "timeout", data, i.delim);
|
|
}
|
|
if (lockRun) unlock();
|
|
}
|
|
#endif
|
|
|
|
|
|
double PITimer::elapsed_n() {
|
|
#ifdef WINDOWS
|
|
t_cur = GetCurrentTime();
|
|
return (t_cur * 1000000. - t_st * 1000000.);
|
|
#else
|
|
clock_gettime(0, &t_cur);
|
|
return (t_cur.tv_sec * 1.e+9 + t_cur.tv_nsec) -
|
|
(t_st.tv_sec * 1.e+9 + t_st.tv_nsec);
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::elapsed_u() {
|
|
#ifdef WINDOWS
|
|
t_cur = GetCurrentTime();
|
|
return (t_cur * 1000. - t_st * 1000.);
|
|
#else
|
|
clock_gettime(0, &t_cur);
|
|
return (t_cur.tv_sec * 1.e+6 + (t_cur.tv_nsec / 1.e+3)) -
|
|
(t_st.tv_sec * 1.e+6 + (t_st.tv_nsec / 1.e+3));
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::elapsed_m() {
|
|
#ifdef WINDOWS
|
|
t_cur = GetCurrentTime();
|
|
return (double)(t_cur - t_st);
|
|
#else
|
|
clock_gettime(0, &t_cur);
|
|
return (t_cur.tv_sec * 1.e+3 + (t_cur.tv_nsec / 1.e+6)) -
|
|
(t_st.tv_sec * 1.e+3 + (t_st.tv_nsec / 1.e+6));
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::elapsed_s() {
|
|
#ifdef WINDOWS
|
|
t_cur = GetCurrentTime();
|
|
return (t_cur / 1000. - t_st / 1000.);
|
|
#else
|
|
clock_gettime(0, &t_cur);
|
|
return (t_cur.tv_sec + (t_cur.tv_nsec / 1.e+9)) -
|
|
(t_st.tv_sec + (t_st.tv_nsec / 1.e+9));
|
|
#endif
|
|
}
|
|
|
|
|
|
PITime currentTime() {
|
|
time_t rt = time(0);
|
|
tm * pt = localtime(&rt);
|
|
PITime t;
|
|
t.seconds = pt->tm_sec;
|
|
t.minutes = pt->tm_min;
|
|
t.hours = pt->tm_hour;
|
|
return t;
|
|
}
|
|
|
|
|
|
PIDate currentDate() {
|
|
time_t rt = time(0);
|
|
tm * pt = localtime(&rt);
|
|
PIDate d;
|
|
d.day = pt->tm_mday;
|
|
d.month = pt->tm_mon + 1;
|
|
d.year = pt->tm_year + 1900;
|
|
return d;
|
|
}
|
|
|
|
|
|
PIString time2string(const PITime & time, const PIString & format) {
|
|
PIString ts = format;
|
|
ts.replace("hh", PIString::fromNumber(time.hours).expandLeftTo(2, '0'));
|
|
ts.replace("h", PIString::fromNumber(time.hours));
|
|
ts.replace("mm", PIString::fromNumber(time.minutes).expandLeftTo(2, '0'));
|
|
ts.replace("m", PIString::fromNumber(time.minutes));
|
|
ts.replace("ss", PIString::fromNumber(time.seconds).expandLeftTo(2, '0'));
|
|
ts.replace("s", PIString::fromNumber(time.seconds));
|
|
return ts;
|
|
}
|
|
|
|
|
|
PIString date2string(const PIDate & date, const PIString & format) {
|
|
PIString ts = format;
|
|
ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0'));
|
|
ts.replace("yy", PIString::fromNumber(date.year).expandLeftTo(2, '0'));
|
|
ts.replace("y", PIString::fromNumber(date.year));
|
|
ts.replace("mm", PIString::fromNumber(date.month).expandLeftTo(2, '0'));
|
|
ts.replace("m", PIString::fromNumber(date.month));
|
|
ts.replace("dd", PIString::fromNumber(date.day).expandLeftTo(2, '0'));
|
|
ts.replace("d", PIString::fromNumber(date.day));
|
|
return ts;
|
|
}
|