845 lines
24 KiB
C++
845 lines
24 KiB
C++
/*ccc
|
|
PIP - Platform Independent Primitives
|
|
Timer
|
|
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
|
|
|
|
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"
|
|
#include "pisystemtests.h"
|
|
|
|
|
|
/*! \class PITimer
|
|
* \brief Timer
|
|
*
|
|
* \section PITimer_sec0 Synopsis
|
|
* This class implements timer function. PIP timers supports 3 way to tick notify,
|
|
* frequency delimiters and time measurements.
|
|
* \section PITimer_sec1 Notify variants
|
|
* Notify variants:
|
|
* * "slot" - static function with format void func(void * data, int delimiter);
|
|
* * event - \a void timeout(void * data, int delimiter);
|
|
* * virtual function - \a void tick(void * data, int delimiter).
|
|
* All this variant are equivalent, use most applicable.
|
|
* \section PITimer_sec2 Frequency delimiters
|
|
* Frequency delimiter is an integer number and "slot" function. If "slot" function is null
|
|
* timer main "slot" will be used. Each delimiter numbers tick timer will be execute
|
|
* delimiters or timer main "slot" function with \b delimiter value = delimiter number.
|
|
* Example: \snippet pitimer.cpp delimiter
|
|
* \section PITimer_sec3 Time measurements
|
|
* PITimer can be used as time measurer. Function \a reset() set time mark to current
|
|
* system time, then functions double elapsed_*() returns time elapsed from this mark.
|
|
* These functions can returns nano-, micro-, milli- and seconds with suffixes "n", "u", "m"
|
|
* and "s";
|
|
* Example: \snippet pitimer.cpp elapsed
|
|
*/
|
|
|
|
|
|
/*! \class PISystemTime
|
|
* \brief System time
|
|
*
|
|
* \section PISystemTime_sec0 Synopsis
|
|
* This class provide arithmetic functions for POSIX system time.
|
|
* This time represents as seconds and nanosecons in integer formats.
|
|
* You can take current system time with function \a currentSystemTime(),
|
|
* compare times, sum or subtract two times, convert time to/from
|
|
* seconds, milliseconds, microseconds or nanoseconds.
|
|
* \section PISystemTime_sec1 Example
|
|
* \snippet pitimer.cpp system_time
|
|
*/
|
|
|
|
|
|
bool operator ==(const PITime & t0, const PITime & t1) {
|
|
return (t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds);
|
|
}
|
|
bool operator <(const PITime & t0, const PITime & t1) {
|
|
if (t0.hours == t1.hours) {
|
|
if (t0.minutes == t1.minutes) {
|
|
return t0.seconds < t1.seconds;
|
|
} else return t0.minutes < t1.minutes;
|
|
} else return t0.hours < t1.hours;
|
|
}
|
|
bool operator >(const PITime & t0, const PITime & t1) {
|
|
if (t0.hours == t1.hours) {
|
|
if (t0.minutes == t1.minutes) {
|
|
return t0.seconds > t1.seconds;
|
|
} else return t0.minutes > t1.minutes;
|
|
} else return t0.hours > t1.hours;
|
|
}
|
|
|
|
bool operator ==(const PIDate & t0, const PIDate & t1) {
|
|
return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day);
|
|
}
|
|
bool operator <(const PIDate & t0, const PIDate & t1) {
|
|
if (t0.year == t1.year) {
|
|
if (t0.month == t1.month) {
|
|
return t0.day < t1.day;
|
|
} else return t0.month < t1.month;
|
|
} else return t0.year < t1.year;
|
|
}
|
|
bool operator >(const PIDate & t0, const PIDate & t1) {
|
|
if (t0.year == t1.year) {
|
|
if (t0.month == t1.month) {
|
|
return t0.day > t1.day;
|
|
} else return t0.month > t1.month;
|
|
} else return t0.year > t1.year;
|
|
}
|
|
|
|
bool operator ==(const PIDateTime & t0, const PIDateTime & t1) {
|
|
return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day &&
|
|
t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds);
|
|
}
|
|
bool operator <(const PIDateTime & t0, const PIDateTime & t1) {
|
|
if (t0.year == t1.year) {
|
|
if (t0.month == t1.month) {
|
|
if (t0.day == t1.day) {
|
|
if (t0.hours == t1.hours) {
|
|
if (t0.minutes == t1.minutes) {
|
|
return t0.seconds < t1.seconds;
|
|
} else return t0.minutes < t1.minutes;
|
|
} else return t0.hours < t1.hours;
|
|
} else return t0.day < t1.day;
|
|
} else return t0.month < t1.month;
|
|
} else return t0.year < t1.year;
|
|
}
|
|
bool operator >(const PIDateTime & t0, const PIDateTime & t1) {
|
|
if (t0.year == t1.year) {
|
|
if (t0.month == t1.month) {
|
|
if (t0.day == t1.day) {
|
|
if (t0.hours == t1.hours) {
|
|
if (t0.minutes == t1.minutes) {
|
|
return t0.seconds > t1.seconds;
|
|
} else return t0.minutes > t1.minutes;
|
|
} else return t0.hours > t1.hours;
|
|
} else return t0.day > t1.day;
|
|
} else return t0.month > t1.month;
|
|
} else return t0.year > t1.year;
|
|
}
|
|
|
|
|
|
#ifdef PIP_TIMER_RT
|
|
PITimer::TimerPool * pool = 0;
|
|
#endif
|
|
|
|
|
|
PITimer::PITimer(TimerEvent slot, void * data_, bool threaded_)
|
|
#ifndef PIP_TIMER_RT
|
|
: PIThread() {
|
|
#else
|
|
: PIObject() {
|
|
#endif
|
|
ret_func = slot;
|
|
data = data_;
|
|
running_ = false;
|
|
interval_ = 0.;
|
|
#ifdef PIP_TIMER_RT
|
|
piMonitor.timers++;
|
|
ti = -1;
|
|
threaded = threaded_;
|
|
memset(&se, 0, sizeof(se));
|
|
se.sigev_notify = SIGEV_THREAD;
|
|
se.sigev_value.sival_ptr = this;
|
|
se.sigev_notify_function = PITimer::timer_event;
|
|
se.sigev_notify_attributes = 0;
|
|
lockRun = false;
|
|
#else
|
|
deferred_ = false;
|
|
#endif
|
|
reset();
|
|
}
|
|
|
|
|
|
PITimer::PITimer(bool threaded_)
|
|
#ifndef PIP_TIMER_RT
|
|
: PIThread() {
|
|
#else
|
|
: PIObject() {
|
|
#endif
|
|
ret_func = 0;
|
|
data = 0;
|
|
running_ = false;
|
|
interval_ = 0.;
|
|
#ifdef PIP_TIMER_RT
|
|
piMonitor.timers++;
|
|
ti = -1;
|
|
threaded = threaded_;
|
|
memset(&se, 0, sizeof(se));
|
|
se.sigev_notify = SIGEV_THREAD;
|
|
se.sigev_value.sival_ptr = this;
|
|
se.sigev_notify_function = PITimer::timer_event;
|
|
se.sigev_notify_attributes = 0;
|
|
lockRun = false;
|
|
#else
|
|
deferred_ = false;
|
|
#endif
|
|
reset();
|
|
}
|
|
|
|
|
|
PITimer::~PITimer() {
|
|
#ifdef PIP_TIMER_RT
|
|
piMonitor.timers--;
|
|
#endif
|
|
stop();
|
|
}
|
|
|
|
|
|
#ifdef PIP_TIMER_RT
|
|
void PITimer::start(double msecs) {
|
|
if (ti != -1 || msecs < 0 || running_) return;
|
|
interval_ = msecs;
|
|
if (!threaded) {
|
|
ticks = int(msecs);
|
|
if (pool == 0) pool = new TimerPool();
|
|
pool->add(this);
|
|
//cout << "not threaded timer start " << msecs << " msecs\n";
|
|
if (!pool->isRunning()) pool->start();
|
|
running_ = true;
|
|
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);
|
|
//cout << "***create timer " << msecs << " msecs\n";
|
|
if (ti == -1) {
|
|
piCoutObj << "Can`t create timer for " << msecs << " msecs: " << errorString();
|
|
return;
|
|
}
|
|
timer_settime(timer, 0, &spec, 0);
|
|
running_ = true;
|
|
}
|
|
|
|
|
|
void PITimer::deferredStart(double interval_msecs, double delay_msecs) {
|
|
if (ti != -1 || interval_msecs < 0 || running_) return;
|
|
interval_ = interval_msecs;
|
|
spec.it_interval.tv_nsec = ((int)(interval_msecs * 1000) % 1000000) * 1000;
|
|
spec.it_interval.tv_sec = (time_t)(interval_msecs / 1000);
|
|
spec.it_value.tv_nsec = ((int)(delay_msecs * 1000) % 1000000) * 1000;
|
|
spec.it_value.tv_sec = (time_t)(delay_msecs / 1000);
|
|
ti = timer_create(CLOCK_REALTIME, &se, &timer);
|
|
//cout << "***create timer\n";
|
|
if (ti == -1) {
|
|
piCoutObj << "Can`t create timer for " << interval_msecs << " msecs: " << errorString();
|
|
return;
|
|
}
|
|
timer_settime(timer, 0, &spec, 0);
|
|
running_ = true;
|
|
}
|
|
|
|
|
|
void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_datetime) {
|
|
if (ti != -1 || interval_msecs < 0 || running_) return;
|
|
interval_ = interval_msecs;
|
|
spec.it_interval.tv_nsec = ((int)(interval_msecs * 1000) % 1000000) * 1000;
|
|
spec.it_interval.tv_sec = (time_t)(interval_msecs / 1000);
|
|
struct tm dtm;
|
|
memset(&dtm, 0, sizeof(dtm));
|
|
dtm.tm_sec = start_datetime.seconds;
|
|
dtm.tm_min = start_datetime.minutes;
|
|
dtm.tm_hour = start_datetime.hours;
|
|
dtm.tm_mday = start_datetime.day;
|
|
dtm.tm_mon = start_datetime.month - 1;
|
|
dtm.tm_year = start_datetime.year - 1900;
|
|
spec.it_value.tv_nsec = 0;
|
|
spec.it_value.tv_sec = mktime(&dtm);
|
|
ti = timer_create(CLOCK_REALTIME, &se, &timer);
|
|
//cout << "***create timer\n";
|
|
if (ti == -1) {
|
|
piCoutObj << "Can`t create timer for " << interval_msecs << " msecs: " << errorString();
|
|
return;
|
|
}
|
|
timer_settime(timer, TIMER_ABSTIME, &spec, 0);
|
|
running_ = true;
|
|
}
|
|
|
|
|
|
|
|
void PITimer::TimerPool::remove(PITimer * t) {
|
|
mutex.lock();
|
|
for (int i = 0; i < timers.size_s(); ++i)
|
|
if (timers[i].first == t) {
|
|
timers.remove(i);
|
|
mutex.unlock();
|
|
return;
|
|
}
|
|
mutex.unlock();
|
|
}
|
|
|
|
|
|
void PITimer::TimerPool::begin() {
|
|
//cout << "pool begin\n";
|
|
/*struct sigaction sa;
|
|
sa.sa_flags = 0;
|
|
sa.sa_handler = empty_handler;
|
|
sigemptyset(&sa.sa_mask);
|
|
if (sigaction(SIGALRM, &sa, 0) == -1) {
|
|
piCoutObj << "sigaction error: " << errorString();
|
|
stop();
|
|
return;
|
|
}*/
|
|
sigemptyset(&ss);
|
|
sigaddset(&ss, SIGALRM);
|
|
memset(&se, 0, sizeof(se));
|
|
se.sigev_notify = SIGEV_SIGNAL;
|
|
se.sigev_signo = SIGALRM;
|
|
spec.it_interval.tv_nsec = 1000000;
|
|
spec.it_interval.tv_sec = 0;
|
|
spec.it_value = spec.it_interval;
|
|
//cout << "***create pool timer\n";
|
|
if (timer_create(CLOCK_REALTIME, &se, &timer) == -1) {
|
|
piCoutObj << "Can`t create timer for pool: " << errorString();
|
|
stop();
|
|
return;
|
|
}
|
|
if (timer_settime(timer, 0, &spec, 0) == -1) {
|
|
piCoutObj << "Can`t set timer for pool: " << errorString();
|
|
stop();
|
|
return;
|
|
}
|
|
ti = 1;
|
|
}
|
|
|
|
|
|
void PITimer::TimerPool::run() {
|
|
//cout << "wait ...\n";
|
|
sigwait(&ss, &si);
|
|
//cout << "ok\n";
|
|
mutex.lock();
|
|
//cout << "* pool tick , pool = " << this <<", timers = " << timers.size()<<"\n";
|
|
for (int i = 0; i < timers.size_s(); ++i) {
|
|
TimerPair & ct(timers[i]);
|
|
sv.sival_ptr = ct.first;
|
|
ct.second++;
|
|
//cout << "** pool tick for " << ct.first << ", cnt " << ct.second << ", " << ct.first->ticks << "\n";
|
|
if (ct.second >= ct.first->ticks) {
|
|
//cout << "*** timer "<<ct.first<<" tick start\n";
|
|
PITimer::timer_event(sv);
|
|
//cout << "*** timer "<<ct.first<<" tick end\n";
|
|
ct.second = 0;
|
|
}
|
|
}
|
|
mutex.unlock();
|
|
}
|
|
|
|
|
|
|
|
void PITimer::stop() {
|
|
if (!running_) return;
|
|
running_ = false;
|
|
if (!threaded) {
|
|
if (pool != 0) {
|
|
pool->remove(this);
|
|
if (pool->isEmpty()) pool->terminate();
|
|
}
|
|
}
|
|
if (ti != -1) timer_delete(timer);
|
|
ti = -1;
|
|
interval_ = 0.;
|
|
}
|
|
|
|
|
|
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);
|
|
ct->timeout(ct->data, 1);
|
|
ct->tick(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);
|
|
ct->timeout(ct->data, i.delim);
|
|
ct->tick(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::start(double msecs) {
|
|
if (msecs < 0 || running_) return;
|
|
interval_ = msecs;
|
|
inc_time = PISystemTime::fromMilliseconds(msecs);
|
|
st_time = currentSystemTime() + inc_time;
|
|
deferred_ = false;
|
|
running_ = true;
|
|
PIThread::start();
|
|
}
|
|
|
|
|
|
void PITimer::deferredStart(double interval_msecs, double delay_msecs) {
|
|
//piCoutObj << "defStart exec with" << delay_msecs << interval_msecs;
|
|
if (interval_msecs < 0 || running_) return;
|
|
interval_ = interval_msecs;
|
|
PISystemTime cst = currentSystemTime();
|
|
inc_time = PISystemTime::fromMilliseconds(interval_msecs);
|
|
st_time = currentSystemTime() + PISystemTime::fromMilliseconds(delay_msecs);
|
|
if (st_time < cst) st_time = cst;
|
|
running_ = deferred_ = true;
|
|
PIThread::start();
|
|
//piCoutObj << "timer start def";
|
|
}
|
|
|
|
|
|
void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_datetime) {
|
|
//piCoutObj << "defStart exec to" << start_datetime.toString() << interval_msecs;
|
|
if (interval_msecs < 0 || running_) return;
|
|
interval_ = interval_msecs;
|
|
PISystemTime cst = currentSystemTime();
|
|
inc_time = PISystemTime::fromMilliseconds(interval_msecs);
|
|
st_time = start_datetime.toSystemTime();
|
|
if (st_time < cst) st_time = cst;
|
|
running_ = deferred_ = true;
|
|
PIThread::start();
|
|
//piCoutObj << "timer start def";
|
|
}
|
|
|
|
|
|
void PITimer::run() {
|
|
if (!running_) return;
|
|
while (deferred_) {
|
|
PISystemTime tst = st_time - currentSystemTime();
|
|
if (tst.seconds > 0) {
|
|
piMSleep(100);
|
|
if (!running_) return;
|
|
continue;
|
|
}
|
|
if (tst.nanoseconds > 100000000) {
|
|
piMSleep(100);
|
|
if (!running_) return;
|
|
continue;
|
|
}
|
|
tst.sleep();
|
|
deferred_ = false;
|
|
if (!running_) return;
|
|
}
|
|
#ifdef WINDOWS
|
|
tt_st = __PIQueryPerformanceCounter();
|
|
#else
|
|
(st_time - currentSystemTime()).sleep();
|
|
st_time += inc_time;
|
|
#endif
|
|
//if (lockRun) lock();
|
|
if (ret_func != 0) ret_func(data, 1);
|
|
timeout(data, 1);
|
|
tick(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);
|
|
timeout(data, i.delim);
|
|
tick(data, i.delim);
|
|
}
|
|
#ifdef WINDOWS
|
|
tt_cur = __PIQueryPerformanceCounter();
|
|
double cdelay = interval_ - ((tt_cur - tt_st) / double(__pi_perf_freq) * 1.E+3);
|
|
if (cdelay > 0.) Sleep(piRoundd(cdelay));
|
|
#endif
|
|
//if (lockRun) unlock();
|
|
}
|
|
|
|
#endif
|
|
|
|
double PITimer::elapsed_n() {
|
|
#ifdef WINDOWS
|
|
pc_cur = __PIQueryPerformanceCounter();
|
|
return ((__pi_perf_freq > 0) ? ((pc_cur - pc_st) / double(__pi_perf_freq) * 1.E+9) : -1.);
|
|
//t_cur = GetCurrentTime();
|
|
//return (t_cur - t_st) * 1000000.;
|
|
#else
|
|
# ifdef MAC_OS
|
|
clock_get_time(__pi_mac_clock, &t_cur);
|
|
# else
|
|
clock_gettime(0, &t_cur);
|
|
# endif
|
|
return (t_cur.tv_sec - t_st.tv_sec) * 1.e+9 + (t_cur.tv_nsec - t_st.tv_nsec - PISystemTests::time_elapsed_ns);
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::elapsed_u() {
|
|
#ifdef WINDOWS
|
|
pc_cur = __PIQueryPerformanceCounter();
|
|
return ((__pi_perf_freq > 0) ? ((pc_cur - pc_st) / double(__pi_perf_freq) * 1.E+6) : -1.);
|
|
//t_cur = GetCurrentTime();
|
|
//return (t_cur - t_st) * 1000.;
|
|
#else
|
|
# ifdef MAC_OS
|
|
clock_get_time(__pi_mac_clock, &t_cur);
|
|
# else
|
|
clock_gettime(0, &t_cur);
|
|
# endif
|
|
return (t_cur.tv_sec - t_st.tv_sec) * 1.e+6 + (t_cur.tv_nsec - t_st.tv_nsec - PISystemTests::time_elapsed_ns) / 1.e+3;
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::elapsed_m() {
|
|
#ifdef WINDOWS
|
|
pc_cur = __PIQueryPerformanceCounter();
|
|
return ((__pi_perf_freq > 0) ? ((pc_cur - pc_st) / double(__pi_perf_freq) * 1.E+3) : -1.);
|
|
//t_cur = GetCurrentTime();
|
|
//return (double)(t_cur - t_st);
|
|
#else
|
|
# ifdef MAC_OS
|
|
clock_get_time(__pi_mac_clock, &t_cur);
|
|
# else
|
|
clock_gettime(0, &t_cur);
|
|
# endif
|
|
return (t_cur.tv_sec - t_st.tv_sec) * 1.e+3 + (t_cur.tv_nsec - t_st.tv_nsec - PISystemTests::time_elapsed_ns) / 1.e+6;
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::elapsed_s() {
|
|
#ifdef WINDOWS
|
|
pc_cur = __PIQueryPerformanceCounter();
|
|
return ((__pi_perf_freq > 0) ? ((pc_cur - pc_st) / double(__pi_perf_freq)) : -1.);
|
|
//t_cur = GetCurrentTime();
|
|
//return (t_cur - t_st) / 1000.;
|
|
#else
|
|
# ifdef MAC_OS
|
|
clock_get_time(__pi_mac_clock, &t_cur);
|
|
# else
|
|
clock_gettime(0, &t_cur);
|
|
# endif
|
|
return (t_cur.tv_sec - t_st.tv_sec) + (t_cur.tv_nsec - t_st.tv_nsec - PISystemTests::time_elapsed_ns) / 1.e+9;
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::reset_time_n() {
|
|
#ifdef WINDOWS
|
|
return t_st * 1.e+6;
|
|
#else
|
|
return t_st.tv_sec * 1.e+9 + t_st.tv_nsec;
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::reset_time_u() {
|
|
#ifdef WINDOWS
|
|
return t_st * 1.e+3;
|
|
#else
|
|
return t_st.tv_sec * 1.e+6 + t_st.tv_nsec / 1.e+3;
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::reset_time_m() {
|
|
#ifdef WINDOWS
|
|
return (double)t_st;
|
|
#else
|
|
return t_st.tv_sec * 1.e+3 + t_st.tv_nsec / 1.e+6;
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::reset_time_s() {
|
|
#ifdef WINDOWS
|
|
return t_st / 1000.;
|
|
#else
|
|
return t_st.tv_sec + t_st.tv_nsec / 1.e+9;
|
|
#endif
|
|
}
|
|
|
|
|
|
PISystemTime PITimer::reset_time() {
|
|
#ifdef WINDOWS
|
|
return PISystemTime(t_st / 1000, (t_st % 1000) * 1000000);
|
|
#else
|
|
return PISystemTime(t_st.tv_sec, t_st.tv_nsec);
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::elapsed_system_n() {
|
|
#ifdef WINDOWS
|
|
llong pc_cur = __PIQueryPerformanceCounter();
|
|
return ((__pi_perf_freq > 0) ? (pc_cur / double(__pi_perf_freq) * 1.E+9) : -1.);
|
|
//long t_cur = GetCurrentTime();
|
|
//return (t_cur * 1000000.);
|
|
#else
|
|
# ifdef MAC_OS
|
|
mach_timespec_t t_cur;
|
|
clock_get_time(__pi_mac_clock, &t_cur);
|
|
# else
|
|
timespec t_cur;
|
|
clock_gettime(0, &t_cur);
|
|
# endif
|
|
return (t_cur.tv_sec * 1.e+9 + t_cur.tv_nsec);
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::elapsed_system_u() {
|
|
#ifdef WINDOWS
|
|
llong pc_cur = __PIQueryPerformanceCounter();
|
|
return ((__pi_perf_freq > 0) ? (pc_cur / double(__pi_perf_freq) * 1.E+6) : -1.);
|
|
//long t_cur = GetCurrentTime();
|
|
//return (t_cur * 1000.);
|
|
#else
|
|
# ifdef MAC_OS
|
|
mach_timespec_t t_cur;
|
|
clock_get_time(__pi_mac_clock, &t_cur);
|
|
# else
|
|
timespec t_cur;
|
|
clock_gettime(0, &t_cur);
|
|
# endif
|
|
return (t_cur.tv_sec * 1.e+6 + (t_cur.tv_nsec / 1.e+3));
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::elapsed_system_m() {
|
|
#ifdef WINDOWS
|
|
llong pc_cur = __PIQueryPerformanceCounter();
|
|
return ((__pi_perf_freq > 0) ? (pc_cur / double(__pi_perf_freq) * 1.E+3) : -1.);
|
|
//long t_cur = GetCurrentTime();
|
|
//return (double)t_cur;
|
|
#else
|
|
# ifdef MAC_OS
|
|
mach_timespec_t t_cur;
|
|
clock_get_time(__pi_mac_clock, &t_cur);
|
|
# else
|
|
timespec t_cur;
|
|
clock_gettime(0, &t_cur);
|
|
# endif
|
|
return (t_cur.tv_sec * 1.e+3 + (t_cur.tv_nsec / 1.e+6));
|
|
#endif
|
|
}
|
|
|
|
|
|
double PITimer::elapsed_system_s() {
|
|
#ifdef WINDOWS
|
|
llong pc_cur = __PIQueryPerformanceCounter();
|
|
return ((__pi_perf_freq > 0) ? (pc_cur / double(__pi_perf_freq)) : -1.);
|
|
//long t_cur = GetCurrentTime();
|
|
//return (t_cur / 1000.);
|
|
#else
|
|
# ifdef MAC_OS
|
|
mach_timespec_t t_cur;
|
|
clock_get_time(__pi_mac_clock, &t_cur);
|
|
# else
|
|
timespec t_cur;
|
|
clock_gettime(0, &t_cur);
|
|
# endif
|
|
return (t_cur.tv_sec + (t_cur.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;
|
|
}
|
|
|
|
|
|
PIDateTime currentDateTime() {
|
|
time_t rt = time(0);
|
|
tm * pt = localtime(&rt);
|
|
PIDateTime dt;
|
|
dt.milliseconds = 0;
|
|
dt.seconds = pt->tm_sec;
|
|
dt.minutes = pt->tm_min;
|
|
dt.hours = pt->tm_hour;
|
|
dt.day = pt->tm_mday;
|
|
dt.month = pt->tm_mon + 1;
|
|
dt.year = pt->tm_year + 1900;
|
|
return dt;
|
|
}
|
|
|
|
|
|
PISystemTime currentSystemTime() {
|
|
#ifdef WINDOWS
|
|
FILETIME ft, sft;
|
|
GetSystemTimeAsFileTime(&ft);
|
|
sft.dwHighDateTime = ft.dwHighDateTime - __pi_ftjan1970.dwHighDateTime;
|
|
if (ft.dwLowDateTime < __pi_ftjan1970.dwLowDateTime) {
|
|
sft.dwLowDateTime = ft.dwLowDateTime + (0xFFFFFFFF - __pi_ftjan1970.dwLowDateTime);
|
|
sft.dwHighDateTime++;
|
|
} else
|
|
sft.dwLowDateTime = ft.dwLowDateTime - __pi_ftjan1970.dwLowDateTime;
|
|
return PISystemTime(sft.dwHighDateTime * 100 + sft.dwLowDateTime / 10000000, (sft.dwLowDateTime % 10000000) * 100);
|
|
//long t_cur = GetCurrentTime();
|
|
//return PISystemTime(t_cur / 1000, (t_cur % 1000) * 1000000);
|
|
#else
|
|
# ifdef MAC_OS
|
|
mach_timespec_t t_cur;
|
|
clock_get_time(__pi_mac_clock, &t_cur);
|
|
# else
|
|
timespec t_cur;
|
|
clock_gettime(0, &t_cur);
|
|
# endif
|
|
return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec);
|
|
#endif
|
|
}
|
|
|
|
|
|
PIString PITime::toString(const PIString & format) const {
|
|
PIString ts = format;
|
|
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0'));
|
|
ts.replace("h", PIString::fromNumber(hours));
|
|
ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0'));
|
|
ts.replace("m", PIString::fromNumber(minutes));
|
|
ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0'));
|
|
ts.replace("s", PIString::fromNumber(seconds));
|
|
ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0'));
|
|
ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0'));
|
|
ts.replace("z", PIString::fromNumber(milliseconds));
|
|
return ts;
|
|
}
|
|
|
|
|
|
PIString PIDate::toString(const PIString & format) const {
|
|
PIString ts = format;
|
|
ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
|
|
ts.replace("yy", PIString::fromNumber(year).right(2));
|
|
ts.replace("y", PIString::fromNumber(year).right(1));
|
|
ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0'));
|
|
ts.replace("M", PIString::fromNumber(month));
|
|
ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0'));
|
|
ts.replace("d", PIString::fromNumber(day));
|
|
return ts;
|
|
}
|
|
|
|
|
|
PIString PIDateTime::toString(const PIString & format) const {
|
|
PIString ts = format;
|
|
ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
|
|
ts.replace("yy", PIString::fromNumber(year).right(2));
|
|
ts.replace("y", PIString::fromNumber(year).right(1));
|
|
ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0'));
|
|
ts.replace("M", PIString::fromNumber(month));
|
|
ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0'));
|
|
ts.replace("d", PIString::fromNumber(day));
|
|
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0'));
|
|
ts.replace("h", PIString::fromNumber(hours));
|
|
ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0'));
|
|
ts.replace("m", PIString::fromNumber(minutes));
|
|
ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0'));
|
|
ts.replace("s", PIString::fromNumber(seconds));
|
|
ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0'));
|
|
ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0'));
|
|
ts.replace("z", PIString::fromNumber(milliseconds));
|
|
return ts;
|
|
}
|
|
|
|
|
|
time_t PIDateTime::toSecondSinceEpoch() const {
|
|
tm pt;
|
|
pt.tm_sec = seconds;
|
|
pt.tm_min = minutes;
|
|
pt.tm_hour = hours;
|
|
pt.tm_mday = day;
|
|
pt.tm_mon = month - 1;
|
|
pt.tm_year = year - 1900;
|
|
return mktime(&pt);
|
|
}
|
|
|
|
|
|
PIDateTime PIDateTime::fromSecondSinceEpoch(const time_t sec) {
|
|
tm * pt = localtime(&sec);
|
|
PIDateTime dt;
|
|
dt.seconds = pt->tm_sec;
|
|
dt.minutes = pt->tm_min;
|
|
dt.hours = pt->tm_hour;
|
|
dt.day = pt->tm_mday;
|
|
dt.month = pt->tm_mon + 1;
|
|
dt.year = pt->tm_year + 1900;
|
|
return dt;
|
|
|
|
}
|
|
|
|
|
|
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).right(2));
|
|
ts.replace("y", PIString::fromNumber(date.year).right(1));
|
|
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;
|
|
}
|
|
|
|
|
|
PIString datetime2string(const PIDateTime & date, const PIString & format) {
|
|
PIString ts = format;
|
|
ts.replace("hh", PIString::fromNumber(date.hours).expandLeftTo(2, '0'));
|
|
ts.replace("h", PIString::fromNumber(date.hours));
|
|
ts.replace("mm", PIString::fromNumber(date.minutes).expandLeftTo(2, '0'));
|
|
ts.replace("m", PIString::fromNumber(date.minutes));
|
|
ts.replace("ss", PIString::fromNumber(date.seconds).expandLeftTo(2, '0'));
|
|
ts.replace("s", PIString::fromNumber(date.seconds));
|
|
ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0'));
|
|
ts.replace("yy", PIString::fromNumber(date.year).right(2));
|
|
ts.replace("y", PIString::fromNumber(date.year).right(1));
|
|
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;
|
|
}
|