18.03.2013 - Bug fixes, add in/out speed diagnostic to PIProtocol, fixed PIConsole tab switch segfault, PIObject EVENT / EVENT_HANDLER mechanism update - new EVENT macros that use EVENT_HANDLER with raiseEvent implementation.

This allow compile check event for CONNECT and use EVENT as CONNECT target, also raise event now is simple execute EVENT function.
This commit is contained in:
peri4
2013-03-18 12:07:44 +04:00
parent cfc5eed75e
commit 66c53a27fc
72 changed files with 4407 additions and 960 deletions

View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Timer
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
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
@@ -18,49 +18,87 @@
*/
#include "pitimer.h"
#include "pisystemtests.h"
PITimer::PITimer(TimerEvent slot, void * data_)
#ifdef WINDOWS
#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_;
#ifndef WINDOWS
#ifdef PIP_TIMER_RT
piMonitor.timers++;
ti = -1;
threaded = threaded_;
running = false;
memset(&se, 0, sizeof(se));
se.sigev_notify = SIGEV_THREAD;
se.sigev_value.sival_ptr = this;
se.sigev_notify_function = timer_event;
se.sigev_notify_function = PITimer::timer_event;
se.sigev_notify_attributes = 0;
lockRun = false;
#endif
reset();
}
PITimer::PITimer(bool threaded_)
#ifndef PIP_TIMER_RT
: PIThread() {
#else
: PIObject() {
#endif
ret_func = 0;
data = 0;
#ifdef PIP_TIMER_RT
piMonitor.timers++;
ti = -1;
threaded = threaded_;
running = false;
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;
#endif
reset();
/*addEvent<void*, int>("timeout");
addEventHandler<double>(HANDLER(PITimer, start));
addEventHandler(HANDLER(PITimer, stop));
addEventHandler(HANDLER(PITimer, reset));*/
}
PITimer::~PITimer() {
#ifndef WINDOWS
#ifdef PIP_TIMER_RT
piMonitor.timers--;
#endif
stop();
}
#ifndef WINDOWS
#ifdef PIP_TIMER_RT
void PITimer::start(double msecs) {
if (ti == 0 || msecs < 0) return;
if (ti != -1 || msecs < 0 || running) return;
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) {
piCout << "[PITimer] Can`t create timer for " << msecs << " msecs: " << errorString() << endl;
return;
@@ -70,18 +108,146 @@ void PITimer::start(double msecs) {
}
void PITimer::deferredStart(double interval_msecs, double delay_msecs) {
if (ti != -1 || interval_msecs < 0 || running) return;
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) {
piCout << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString() << endl;
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;
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) {
piCout << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString() << endl;
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) {
piCout << "[PITimer] sigaction error: " << errorString() << endl;
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) {
piCout << "[PITimer] Can`t create timer for pool: " << errorString() << endl;
stop();
return;
}
if (timer_settime(timer, 0, &spec, 0) == -1) {
piCout << "[PITimer] Can`t set timer for pool: " << errorString() << endl;
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;
}
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);
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);
raiseEvent<void*, int>(ct, "timeout", ct->data, i.delim);
ct->timeout(ct->data, i.delim);
ct->tick(ct->data, i.delim);
}
if (ct->lockRun) ct->unlock();
}
@@ -101,32 +267,48 @@ bool PITimer::waitForFinish(int timeout_msecs) {
return cnt < timeout_msecs;
}
#else
void PITimer::start(double msecs) {
if (msecs < 0 || running) return;
inc_time = PISystemTime::fromMilliseconds(msecs);
st_time = currentSystemTime() + inc_time;
PIThread::start();
}
void PITimer::run() {
if (!running) return;
(st_time - currentSystemTime()).sleep();
st_time += inc_time;
if (lockRun) lock();
if (ret_func != 0) ret_func(data, 1);
raiseEvent<void*, int>(this, "timeout", 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);
raiseEvent<void*, int>(this, "timeout", data, i.delim);
timeout(data, i.delim);
tick(data, i.delim);
}
if (lockRun) unlock();
}
#endif
#endif
double PITimer::elapsed_n() {
#ifdef WINDOWS
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);
return (t_cur.tv_sec - t_st.tv_sec) * 1.e+9 + (t_cur.tv_nsec - t_st.tv_nsec);
# 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
}
@@ -136,8 +318,12 @@ double PITimer::elapsed_u() {
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);
return (t_cur.tv_sec - t_st.tv_sec) * 1.e+6 + (t_cur.tv_nsec - t_st.tv_nsec) / 1.e+3;
# 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
}
@@ -147,8 +333,12 @@ double PITimer::elapsed_m() {
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);
return (t_cur.tv_sec - t_st.tv_sec) * 1.e+3 + (t_cur.tv_nsec - t_st.tv_nsec) / 1.e+6;
# 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
}
@@ -158,18 +348,20 @@ double PITimer::elapsed_s() {
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);
return (t_cur.tv_sec - t_st.tv_sec) + (t_cur.tv_nsec - t_st.tv_nsec) / 1.e+9;
# 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
t_cur = GetCurrentTime();
return t_st * 1000000.;
return t_st * 1.e+6;
#else
clock_gettime(0, &t_cur);
return t_st.tv_sec * 1.e+9 + t_st.tv_nsec;
#endif
}
@@ -177,10 +369,8 @@ double PITimer::reset_time_n() {
double PITimer::reset_time_u() {
#ifdef WINDOWS
t_cur = GetCurrentTime();
return (t_cur - t_st) * 1000.;
return t_st * 1.e+3;
#else
clock_gettime(0, &t_cur);
return t_st.tv_sec * 1.e+6 + t_st.tv_nsec / 1.e+3;
#endif
}
@@ -188,10 +378,8 @@ double PITimer::reset_time_u() {
double PITimer::reset_time_m() {
#ifdef WINDOWS
t_cur = GetCurrentTime();
return (double)(t_cur - t_st);
return (double)t_st;
#else
clock_gettime(0, &t_cur);
return t_st.tv_sec * 1.e+3 + t_st.tv_nsec / 1.e+6;
#endif
}
@@ -199,22 +387,34 @@ double PITimer::reset_time_m() {
double PITimer::reset_time_s() {
#ifdef WINDOWS
t_cur = GetCurrentTime();
return (t_cur - t_st) / 1000.;
return t_st / 1000.;
#else
clock_gettime(0, &t_cur);
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
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
}
@@ -225,8 +425,13 @@ double PITimer::elapsed_system_u() {
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
}
@@ -237,8 +442,13 @@ double PITimer::elapsed_system_m() {
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
}
@@ -249,8 +459,13 @@ double PITimer::elapsed_system_s() {
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
}
@@ -278,6 +493,37 @@ PIDate currentDate() {
}
PIDateTime currentDateTime() {
time_t rt = time(0);
tm * pt = localtime(&rt);
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;
}
PISystemTime currentSystemTime() {
#ifdef WINDOWS
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) {
PIString ts = format;
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0'));
@@ -293,10 +539,29 @@ PIString PITime::toString(const PIString & format) {
PIString PIDate::toString(const PIString & format) {
PIString ts = format;
ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
ts.replace("yy", PIString::fromNumber(year).expandLeftTo(2, '0'));
ts.replace("y", PIString::fromNumber(year));
ts.replace("mm", PIString::fromNumber(month).expandLeftTo(2, '0'));
ts.replace("m", PIString::fromNumber(month));
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) {
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("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;
@@ -318,10 +583,29 @@ PIString time2string(const PITime & time, const PIString & format) {
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("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;