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:
@@ -1,10 +1,10 @@
|
|||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
||||||
project(PIP)
|
project(PIP)
|
||||||
set(PIP_MAJOR 3)
|
set(PIP_MAJOR 4)
|
||||||
set(PIP_MINOR 21)
|
set(PIP_MINOR 0)
|
||||||
set(PIP_REVISION 0)
|
set(PIP_REVISION 0)
|
||||||
set(PIP_SUFFIX )
|
set(PIP_SUFFIX _alpha)
|
||||||
set(PIP_COMPANY SHS)
|
set(PIP_COMPANY SHS)
|
||||||
set(PIP_DOMAIN org.SHS)
|
set(PIP_DOMAIN org.SHS)
|
||||||
|
|
||||||
@@ -247,18 +247,6 @@ if(PIP_MATH_YN)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# Check if RT timers exists
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES time.h)
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES )
|
|
||||||
if((NOT DEFINED ENV{QNX_HOST}) AND (NOT APPLE) AND (NOT WIN32) AND (NOT DEFINED ANDROID_PLATFORM) AND (NOT PIP_FREERTOS))
|
|
||||||
list(APPEND LIBS_MAIN rt)
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES rt)
|
|
||||||
endif()
|
|
||||||
CHECK_FUNCTION_EXISTS(timer_create PIP_TIMER_RT_0)
|
|
||||||
CHECK_FUNCTION_EXISTS(timer_settime PIP_TIMER_RT_1)
|
|
||||||
CHECK_FUNCTION_EXISTS(timer_delete PIP_TIMER_RT_2)
|
|
||||||
|
|
||||||
|
|
||||||
# Check if build debug version
|
# Check if build debug version
|
||||||
if (PIP_BUILD_DEBUG)
|
if (PIP_BUILD_DEBUG)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -Wall")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -Wall")
|
||||||
@@ -317,15 +305,6 @@ list(APPEND HDRS ${_PIP_DEFS_FILE})
|
|||||||
#message("${_PIP_DEFS_CHANGED}")
|
#message("${_PIP_DEFS_CHANGED}")
|
||||||
|
|
||||||
|
|
||||||
# Check if RT timers exists
|
|
||||||
if(PIP_TIMER_RT_0 AND PIP_TIMER_RT_1 AND PIP_TIMER_RT_2)
|
|
||||||
set(PIP_TIMERS "Thread, ThreadRT, Pool")
|
|
||||||
add_definitions(-DPIP_TIMER_RT)
|
|
||||||
else()
|
|
||||||
set(PIP_TIMERS "Thread, Pool")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Add main library
|
# Add main library
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
@@ -673,7 +652,6 @@ message("")
|
|||||||
message(" Options:")
|
message(" Options:")
|
||||||
message(" std::iostream: ${PIP_STD_IOSTREAM}")
|
message(" std::iostream: ${PIP_STD_IOSTREAM}")
|
||||||
message(" ICU strings : ${PIP_ICU}")
|
message(" ICU strings : ${PIP_ICU}")
|
||||||
message(" Timer types : ${PIP_TIMERS}")
|
|
||||||
message(" Introspection: ${PIP_INTROSPECTION}")
|
message(" Introspection: ${PIP_INTROSPECTION}")
|
||||||
message(" Coverage : ${PIP_COVERAGE}")
|
message(" Coverage : ${PIP_COVERAGE}")
|
||||||
if(INTROSPECTION)
|
if(INTROSPECTION)
|
||||||
|
|||||||
@@ -66,10 +66,6 @@ if (NOT BUILDING_PIP)
|
|||||||
find_library(PTHREAD_LIBRARY pthread)
|
find_library(PTHREAD_LIBRARY pthread)
|
||||||
find_library(UTIL_LIBRARY util)
|
find_library(UTIL_LIBRARY util)
|
||||||
set(_PIP_ADD_LIBS_ ${PTHREAD_LIBRARY} ${UTIL_LIBRARY})
|
set(_PIP_ADD_LIBS_ ${PTHREAD_LIBRARY} ${UTIL_LIBRARY})
|
||||||
if((NOT DEFINED ENV{QNX_HOST}) AND (NOT APPLE) AND (NOT PIP_FREERTOS))
|
|
||||||
find_library(RT_LIBRARY rt)
|
|
||||||
list(APPEND _PIP_ADD_LIBS_ ${RT_LIBRARY})
|
|
||||||
endif()
|
|
||||||
list(APPEND PIP_LIBRARY ${_PIP_ADD_LIBS_})
|
list(APPEND PIP_LIBRARY ${_PIP_ADD_LIBS_})
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#include "pip.h"
|
#include "pip.h"
|
||||||
|
|
||||||
//! [delimiter]
|
//! [delimiter]
|
||||||
void tfunc(void * , int delim) {
|
void tfunc(int delim) {
|
||||||
piCout << "tick with delimiter" << delim;
|
piCout << "tick with delimiter" << delim;
|
||||||
};
|
};
|
||||||
void tfunc4(void * , int delim) {
|
void tfunc4(int delim) {
|
||||||
piCout << "tick4 with delimiter" << delim;
|
piCout << "tick4 with delimiter" << delim;
|
||||||
};
|
};
|
||||||
int main() {
|
int main() {
|
||||||
@@ -13,8 +13,7 @@ int main() {
|
|||||||
timer.addDelimiter(4, tfunc4);
|
timer.addDelimiter(4, tfunc4);
|
||||||
timer.start(50);
|
timer.start(50);
|
||||||
piMSleep(200);
|
piMSleep(200);
|
||||||
timer.stop();
|
timer.stopAndWait();
|
||||||
timer.waitForFinish();
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
/* Result:
|
/* Result:
|
||||||
@@ -29,14 +28,14 @@ tick4 with delimiter 4
|
|||||||
//! [delimiter]
|
//! [delimiter]
|
||||||
//! [elapsed]
|
//! [elapsed]
|
||||||
int main() {
|
int main() {
|
||||||
PITimer timer;
|
PITimeMeasurer tm;
|
||||||
piMSleep(100);
|
piMSleep(100);
|
||||||
piCout << "elapsed" << timer.elapsed_m() << "ms";
|
piCout << "elapsed" << tm.elapsed_m() << "ms";
|
||||||
piMSleep(100);
|
piMSleep(100);
|
||||||
piCout << "elapsed" << timer.elapsed_m() << "ms";
|
piCout << "elapsed" << tm.elapsed_m() << "ms";
|
||||||
timer.reset();
|
tm.reset();
|
||||||
piMSleep(150);
|
piMSleep(150);
|
||||||
piCout << "elapsed" << timer.elapsed_s() << "s";
|
piCout << "elapsed" << tm.elapsed_s() << "s";
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
/* Result:
|
/* Result:
|
||||||
@@ -47,22 +46,21 @@ elapsed 0.15 s
|
|||||||
//! [elapsed]
|
//! [elapsed]
|
||||||
//! [system_time]
|
//! [system_time]
|
||||||
int main() {
|
int main() {
|
||||||
PISystemTime t0; // s = ns = 0
|
PISystemTime t0; // s = ns = 0
|
||||||
t0.addMilliseconds(200); // s = 0, ns = 200000000
|
t0.addMilliseconds(200); // s = 0, ns = 200000000
|
||||||
t0.addMilliseconds(900); // s = 1, ns = 100000000
|
t0.addMilliseconds(900); // s = 1, ns = 100000000
|
||||||
t0 -= PISystemTime::fromSeconds(0.1); // s = 1, ns = 0
|
t0 -= PISystemTime::fromSeconds(0.1); // s = 1, ns = 0
|
||||||
t0.sleep(); // sleep for 1 second
|
t0.sleep(); // sleep for 1 second
|
||||||
PISystemTime t1;
|
PISystemTime t1;
|
||||||
t0 = currentSystemTime();
|
t0 = PISystemTime::current();
|
||||||
piMSleep(500);
|
piMSleep(500);
|
||||||
t1 = currentSystemTime();
|
t1 = PISystemTime::current();
|
||||||
(t1 - t0).sleep(); // sleep for 500 milliseconds
|
(t1 - t0).sleep(); // sleep for 500 milliseconds
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
//! [system_time]
|
//! [system_time]
|
||||||
|
|
||||||
void _() {
|
void _(){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class MainClass: public PITimer {
|
|||||||
public:
|
public:
|
||||||
MainClass() {}
|
MainClass() {}
|
||||||
protected:
|
protected:
|
||||||
void tick(void * data, int delimiter) {
|
void tick(int delimiter) {
|
||||||
piCout << "timer tick";
|
piCout << "timer tick";
|
||||||
// timer tick
|
// timer tick
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ bool PICloudClient::openDevice() {
|
|||||||
mutex_connect.lock();
|
mutex_connect.lock();
|
||||||
eth.startThreadedRead();
|
eth.startThreadedRead();
|
||||||
// piCoutObj << "connecting...";
|
// piCoutObj << "connecting...";
|
||||||
bool conn_ok = cond_connect.waitFor(mutex_connect, (int)eth.readTimeout());
|
bool conn_ok = cond_connect.waitFor(mutex_connect, eth.readTimeout());
|
||||||
// piCoutObj << "conn_ok" << conn_ok << is_connected;
|
// piCoutObj << "conn_ok" << conn_ok << is_connected;
|
||||||
mutex_connect.unlock();
|
mutex_connect.unlock();
|
||||||
if (!conn_ok) {
|
if (!conn_ok) {
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
#include "picloudserver.h"
|
#include "picloudserver.h"
|
||||||
|
|
||||||
|
#include "piliterals_time.h"
|
||||||
|
|
||||||
|
|
||||||
PICloudServer::PICloudServer(const PIString & path, PIIODevice::DeviceMode mode): PIIODevice(path, mode), PICloudBase() {
|
PICloudServer::PICloudServer(const PIString & path, PIIODevice::DeviceMode mode): PIIODevice(path, mode), PICloudBase() {
|
||||||
PIString server_name = "PCS_" + PIString::fromNumber(randomi() % 1000);
|
PIString server_name = "PCS_" + PIString::fromNumber(randomi() % 1000);
|
||||||
@@ -94,7 +96,7 @@ bool PICloudServer::openDevice() {
|
|||||||
bool op = eth.connect(PINetworkAddress::resolve(path()), false);
|
bool op = eth.connect(PINetworkAddress::resolve(path()), false);
|
||||||
if (op) {
|
if (op) {
|
||||||
eth.startThreadedRead();
|
eth.startThreadedRead();
|
||||||
ping_timer.start(5000);
|
ping_timer.start(5_s);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
ping_timer.stop();
|
ping_timer.stop();
|
||||||
@@ -169,7 +171,7 @@ PICloudServer::Client::Client(PICloudServer * srv, uint id): server(srv), client
|
|||||||
PICloudServer::Client::~Client() {
|
PICloudServer::Client::~Client() {
|
||||||
// piCoutObj << "~PICloudServer::Client..." << this;
|
// piCoutObj << "~PICloudServer::Client..." << this;
|
||||||
close();
|
close();
|
||||||
stopAndWait(10000);
|
stopAndWait(10_s);
|
||||||
// piCoutObj << "~PICloudServer::Client done" << this;
|
// piCoutObj << "~PICloudServer::Client done" << this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "piscreen.h"
|
#include "piscreen.h"
|
||||||
|
|
||||||
#include "piincludes_p.h"
|
#include "piincludes_p.h"
|
||||||
|
#include "piliterals_time.h"
|
||||||
#ifndef WINDOWS
|
#ifndef WINDOWS
|
||||||
# include <fcntl.h>
|
# include <fcntl.h>
|
||||||
# include <sys/ioctl.h>
|
# include <sys/ioctl.h>
|
||||||
@@ -417,8 +418,8 @@ PIScreen::PIScreen(bool startNow, PIKbdListener::KBFunc slot): PIThread(), drawe
|
|||||||
|
|
||||||
PIScreen::~PIScreen() {
|
PIScreen::~PIScreen() {
|
||||||
if (isRunning()) stop();
|
if (isRunning()) stop();
|
||||||
PIThread::waitForFinish(10);
|
PIThread::waitForFinish(100_ms);
|
||||||
listener->waitForFinish(10);
|
listener->waitForFinish(100_ms);
|
||||||
delete listener;
|
delete listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,6 +591,12 @@ void PIScreen::waitForFinish() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIScreen::start(bool wait) {
|
||||||
|
PIThread::start(25_Hz);
|
||||||
|
if (wait) waitForFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIScreen::stop(bool clear) {
|
void PIScreen::stop(bool clear) {
|
||||||
PIThread::stopAndWait();
|
PIThread::stopAndWait();
|
||||||
if (clear) console.clearScreen();
|
if (clear) console.clearScreen();
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "piterminal.h"
|
#include "piterminal.h"
|
||||||
|
|
||||||
#include "piincludes_p.h"
|
#include "piincludes_p.h"
|
||||||
|
#include "piliterals_time.h"
|
||||||
#include "pisharedmemory.h"
|
#include "pisharedmemory.h"
|
||||||
#ifndef MICRO_PIP
|
#ifndef MICRO_PIP
|
||||||
# ifdef WINDOWS
|
# ifdef WINDOWS
|
||||||
@@ -126,7 +127,7 @@ PITerminal::PITerminal(): PIThread() {
|
|||||||
|
|
||||||
PITerminal::~PITerminal() {
|
PITerminal::~PITerminal() {
|
||||||
if (isRunning()) stop();
|
if (isRunning()) stop();
|
||||||
PIThread::waitForFinish(10);
|
PIThread::waitForFinish(1_s);
|
||||||
destroy();
|
destroy();
|
||||||
# ifdef WINDOWS
|
# ifdef WINDOWS
|
||||||
if (PRIVATE->shm) delete PRIVATE->shm;
|
if (PRIVATE->shm) delete PRIVATE->shm;
|
||||||
@@ -915,7 +916,7 @@ bool PITerminal::initialize() {
|
|||||||
# endif
|
# endif
|
||||||
cursor_blink = false;
|
cursor_blink = false;
|
||||||
cursor_tm.reset();
|
cursor_tm.reset();
|
||||||
start(40);
|
start(25_Hz);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -923,7 +924,7 @@ bool PITerminal::initialize() {
|
|||||||
void PITerminal::destroy() {
|
void PITerminal::destroy() {
|
||||||
// piCout << "destroy ...";
|
// piCout << "destroy ...";
|
||||||
stop();
|
stop();
|
||||||
waitForFinish(1000);
|
waitForFinish(1_s);
|
||||||
# ifdef WINDOWS
|
# ifdef WINDOWS
|
||||||
if (PRIVATE->pi.hProcess) {
|
if (PRIVATE->pi.hProcess) {
|
||||||
// piCout << "term";
|
// piCout << "term";
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
#include "pibroadcast.h"
|
#include "pibroadcast.h"
|
||||||
|
|
||||||
|
#include "piliterals_time.h"
|
||||||
|
|
||||||
/** \class PIBroadcast
|
/** \class PIBroadcast
|
||||||
* \brief Broadcast for all interfaces, including loopback
|
* \brief Broadcast for all interfaces, including loopback
|
||||||
*
|
*
|
||||||
@@ -223,7 +225,7 @@ void PIBroadcast::startRead() {
|
|||||||
if (!isRunning()) {
|
if (!isRunning()) {
|
||||||
_started = false;
|
_started = false;
|
||||||
reinit();
|
reinit();
|
||||||
PIThread::start(3000);
|
PIThread::start(3_s);
|
||||||
}
|
}
|
||||||
if (_send_only) return;
|
if (_send_only) return;
|
||||||
PIMutexLocker ml(mcast_mutex);
|
PIMutexLocker ml(mcast_mutex);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "pistreampacker.h"
|
#include "pistreampacker.h"
|
||||||
|
|
||||||
#include "piiodevice.h"
|
#include "piiodevice.h"
|
||||||
|
#include "piliterals_bytes.h"
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
# pragma GCC diagnostic pop
|
# pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
@@ -52,7 +53,7 @@ PIStreamPacker::PIStreamPacker(PIIODevice * dev): PIObject() {
|
|||||||
aggressive_optimization = true;
|
aggressive_optimization = true;
|
||||||
packet_size = -1;
|
packet_size = -1;
|
||||||
size_crypted_size = sizeof(int);
|
size_crypted_size = sizeof(int);
|
||||||
crypt_frag_size = 1024 * 1024;
|
crypt_frag_size = 1_MiB;
|
||||||
max_packet_size = 1400;
|
max_packet_size = 1400;
|
||||||
packet_sign = 0xAFBE;
|
packet_sign = 0xAFBE;
|
||||||
assignDevice(dev);
|
assignDevice(dev);
|
||||||
|
|||||||
@@ -167,7 +167,8 @@ PIKbdListener::PIKbdListener(KBFunc slot, void * _d, bool startNow): PIThread()
|
|||||||
|
|
||||||
|
|
||||||
PIKbdListener::~PIKbdListener() {
|
PIKbdListener::~PIKbdListener() {
|
||||||
terminate();
|
stop();
|
||||||
|
if (!waitForFinish(100_ms)) terminate();
|
||||||
end();
|
end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,10 +73,7 @@ public:
|
|||||||
|
|
||||||
EVENT_HANDLER0(void, waitForFinish);
|
EVENT_HANDLER0(void, waitForFinish);
|
||||||
EVENT_HANDLER0(void, start) { start(false); }
|
EVENT_HANDLER0(void, start) { start(false); }
|
||||||
EVENT_HANDLER1(void, start, bool, wait) {
|
EVENT_HANDLER1(void, start, bool, wait);
|
||||||
PIThread::start(40);
|
|
||||||
if (wait) waitForFinish();
|
|
||||||
}
|
|
||||||
EVENT_HANDLER0(void, stop) { stop(false); }
|
EVENT_HANDLER0(void, stop) { stop(false); }
|
||||||
EVENT_HANDLER1(void, stop, bool, clear);
|
EVENT_HANDLER1(void, stop, bool, clear);
|
||||||
|
|
||||||
|
|||||||
@@ -150,11 +150,6 @@
|
|||||||
//! \~russian Макрос объявлен когда компилятор неизвестен
|
//! \~russian Макрос объявлен когда компилятор неизвестен
|
||||||
# define CC_OTHER
|
# define CC_OTHER
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro is defined when PIP can use "rt" library for \a PITimer::ThreadRT timers implementation
|
|
||||||
//! \~russian Макрос объявлен когда PIP может использовать библиотеку "rt" для \a PITimer::ThreadRT реализации таймера
|
|
||||||
# define PIP_TIMER_RT
|
|
||||||
|
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Macro to declare private section, "export" is optional
|
//! \~english Macro to declare private section, "export" is optional
|
||||||
//! \~russian Макрос для объявления частной секции, "export" необязателен
|
//! \~russian Макрос для объявления частной секции, "export" необязателен
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ void PIIntrospectionThreads::threadStart(PIThread * t) {
|
|||||||
ThreadInfo & ti(threads[t]);
|
ThreadInfo & ti(threads[t]);
|
||||||
ti.id = t->tid();
|
ti.id = t->tid();
|
||||||
ti.priority = t->priority();
|
ti.priority = t->priority();
|
||||||
ti.delay = t->delay_;
|
ti.delay = t->delay_.toMilliseconds();
|
||||||
ti.state = sStarting;
|
ti.state = sStarting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,10 @@
|
|||||||
#include "pibinarylog.h"
|
#include "pibinarylog.h"
|
||||||
|
|
||||||
#include "pidir.h"
|
#include "pidir.h"
|
||||||
#include "piliterals.h"
|
#include "piliterals_bytes.h"
|
||||||
|
#include "piliterals_time.h"
|
||||||
#include "pipropertystorage.h"
|
#include "pipropertystorage.h"
|
||||||
|
#include "pitime.h"
|
||||||
|
|
||||||
#define PIBINARYLOG_VERSION_OLD 0x31
|
#define PIBINARYLOG_VERSION_OLD 0x31
|
||||||
|
|
||||||
@@ -259,9 +261,9 @@ PIString PIBinaryLog::getLogfilePath(const PIString & log_dir, const PIString &
|
|||||||
<< "Creating directory" << dir.path();
|
<< "Creating directory" << dir.path();
|
||||||
dir.make(true);
|
dir.make(true);
|
||||||
}
|
}
|
||||||
const PIString npath = log_dir + PIDir::separator + prefix + PIDateTime::current().toString("yyyy_MM_dd__hh_mm_ss");
|
const PIString npath = log_dir + PIDir::separator + prefix + PIDateTime::current().toString("yyyy_MM_dd__hh_mm_ss");
|
||||||
PIString cnpath = npath + ".binlog";
|
PIString cnpath = npath + ".binlog";
|
||||||
int i = 1;
|
int i = 1;
|
||||||
while (PIFile::isExists(cnpath)) {
|
while (PIFile::isExists(cnpath)) {
|
||||||
cnpath = npath + '_' + PIString::fromNumber(i) + ".binlog";
|
cnpath = npath + '_' + PIString::fromNumber(i) + ".binlog";
|
||||||
i++;
|
i++;
|
||||||
@@ -644,9 +646,9 @@ void PIBinaryLog::parseLog(PIFile * f, PIBinaryLog::BinLogInfo * info, PIVector<
|
|||||||
}
|
}
|
||||||
PIByteArray ba;
|
PIByteArray ba;
|
||||||
Record br;
|
Record br;
|
||||||
br.id = 0;
|
br.id = 0;
|
||||||
br.size = 0;
|
br.size = 0;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
constexpr size_t hdr_size = sizeof(Record) - sizeof(PIByteArray);
|
constexpr size_t hdr_size = sizeof(Record) - sizeof(PIByteArray);
|
||||||
ba.resize(hdr_size);
|
ba.resize(hdr_size);
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -977,16 +979,16 @@ void PIBinaryLog::configureFromVariantDevice(const PIPropertyStorage & d) {
|
|||||||
|
|
||||||
|
|
||||||
void PIBinaryLog::propertyChanged(const char * s) {
|
void PIBinaryLog::propertyChanged(const char * s) {
|
||||||
default_id = property("defaultID").toInt();
|
default_id = property("defaultID").toInt();
|
||||||
rapid_start = property("rapidStart").toBool();
|
rapid_start = property("rapidStart").toBool();
|
||||||
play_mode = (PlayMode)property("playMode").toInt();
|
play_mode = (PlayMode)property("playMode").toInt();
|
||||||
const double ps = property("playSpeed").toDouble();
|
const double ps = property("playSpeed").toDouble();
|
||||||
play_speed = ps > 0. ? 1. / ps : 0.;
|
play_speed = ps > 0. ? 1. / ps : 0.;
|
||||||
play_delay = property("playDelay").toSystemTime();
|
play_delay = property("playDelay").toSystemTime();
|
||||||
split_mode = (SplitMode)property("splitMode").toInt();
|
split_mode = (SplitMode)property("splitMode").toInt();
|
||||||
split_time = property("splitTime").toSystemTime();
|
split_time = property("splitTime").toSystemTime();
|
||||||
split_size = property("splitFileSize").toLLong();
|
split_size = property("splitFileSize").toLLong();
|
||||||
split_count = property("splitRecordCount").toInt();
|
split_count = property("splitRecordCount").toInt();
|
||||||
// piCoutObj << "propertyChanged" << s << play_mode;
|
// piCoutObj << "propertyChanged" << s << play_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -163,8 +163,8 @@ void PIEthernet::construct() {
|
|||||||
setOption(BlockingWrite);
|
setOption(BlockingWrite);
|
||||||
connected_ = connecting_ = listen_threaded = server_bounded = false;
|
connected_ = connecting_ = listen_threaded = server_bounded = false;
|
||||||
sock = sock_s = -1;
|
sock = sock_s = -1;
|
||||||
setReadTimeout(10000.);
|
setReadTimeout(10_s);
|
||||||
setWriteTimeout(10000.);
|
setWriteTimeout(10_s);
|
||||||
setTTL(64);
|
setTTL(64);
|
||||||
setMulticastTTL(1);
|
setMulticastTTL(1);
|
||||||
server_thread_.setData(this);
|
server_thread_.setData(this);
|
||||||
@@ -331,7 +331,7 @@ void PIEthernet::closeSocket(int & sd) {
|
|||||||
|
|
||||||
void PIEthernet::applyTimeouts() {
|
void PIEthernet::applyTimeouts() {
|
||||||
if (sock < 0) return;
|
if (sock < 0) return;
|
||||||
double rtm = readTimeout(), wtm = writeTimeout();
|
PISystemTime rtm = readTimeout(), wtm = writeTimeout();
|
||||||
applyTimeout(sock, SO_RCVTIMEO, rtm);
|
applyTimeout(sock, SO_RCVTIMEO, rtm);
|
||||||
applyTimeout(sock, SO_SNDTIMEO, wtm);
|
applyTimeout(sock, SO_SNDTIMEO, wtm);
|
||||||
if (sock_s != sock && sock_s != -1) {
|
if (sock_s != sock && sock_s != -1) {
|
||||||
@@ -341,17 +341,15 @@ void PIEthernet::applyTimeouts() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIEthernet::applyTimeout(int fd, int opt, double ms) {
|
void PIEthernet::applyTimeout(int fd, int opt, PISystemTime tm) {
|
||||||
if (fd == 0) return;
|
if (fd == 0) return;
|
||||||
// piCoutObj << "setReadIsBlocking" << yes;
|
// piCoutObj << "setReadIsBlocking" << yes;
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
DWORD _tm = ms;
|
DWORD _tm = tm.toMilliseconds();
|
||||||
#else
|
#else
|
||||||
double s = ms / 1000.;
|
|
||||||
timeval _tm;
|
timeval _tm;
|
||||||
_tm.tv_sec = piFloord(s);
|
_tm.tv_sec = tm.seconds;
|
||||||
s -= _tm.tv_sec;
|
_tm.tv_usec = tm.nanoseconds / 1000;
|
||||||
_tm.tv_usec = s * 1000000.;
|
|
||||||
#endif
|
#endif
|
||||||
ethSetsockopt(fd, SOL_SOCKET, opt, &_tm, sizeof(_tm));
|
ethSetsockopt(fd, SOL_SOCKET, opt, &_tm, sizeof(_tm));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,16 +174,16 @@ public:
|
|||||||
Type type() const { return eth_type; }
|
Type type() const { return eth_type; }
|
||||||
|
|
||||||
//! Returns read timeout
|
//! Returns read timeout
|
||||||
double readTimeout() const { return property("readTimeout").toDouble(); }
|
PISystemTime readTimeout() const { return property("readTimeout").toSystemTime(); }
|
||||||
|
|
||||||
//! Returns write timeout
|
//! Returns write timeout
|
||||||
double writeTimeout() const { return property("writeTimeout").toDouble(); }
|
PISystemTime writeTimeout() const { return property("writeTimeout").toSystemTime(); }
|
||||||
|
|
||||||
//! Set timeout for read
|
//! Set timeout for read
|
||||||
void setReadTimeout(double ms) { setProperty("readTimeout", ms); }
|
void setReadTimeout(PISystemTime tm) { setProperty("readTimeout", tm); }
|
||||||
|
|
||||||
//! Set timeout for write
|
//! Set timeout for write
|
||||||
void setWriteTimeout(double ms) { setProperty("writeTimeout", ms); }
|
void setWriteTimeout(PISystemTime tm) { setProperty("writeTimeout", tm); }
|
||||||
|
|
||||||
|
|
||||||
//! Returns TTL (Time To Live)
|
//! Returns TTL (Time To Live)
|
||||||
@@ -437,11 +437,11 @@ public:
|
|||||||
//! \brief ethernet parameters
|
//! \brief ethernet parameters
|
||||||
int parameters;
|
int parameters;
|
||||||
|
|
||||||
//! \brief read timeout, default 1000 ms
|
//! \brief read timeout, default 10 s
|
||||||
double readTimeout;
|
PISystemTime readTimeout;
|
||||||
|
|
||||||
//! \brief write timeout, default 1000 ms
|
//! \brief write timeout, default 10 s
|
||||||
double writeTimeout;
|
PISystemTime writeTimeout;
|
||||||
|
|
||||||
//! \brief time-to-live, default 64
|
//! \brief time-to-live, default 64
|
||||||
int TTL;
|
int TTL;
|
||||||
@@ -475,7 +475,7 @@ protected:
|
|||||||
bool closeDevice() override;
|
bool closeDevice() override;
|
||||||
void closeSocket(int & sd);
|
void closeSocket(int & sd);
|
||||||
void applyTimeouts();
|
void applyTimeouts();
|
||||||
void applyTimeout(int fd, int opt, double ms);
|
void applyTimeout(int fd, int opt, PISystemTime tm);
|
||||||
void applyOptInt(int level, int opt, int val);
|
void applyOptInt(int level, int opt, int val);
|
||||||
|
|
||||||
PRIVATE_DECLARATION(PIP_EXPORT)
|
PRIVATE_DECLARATION(PIP_EXPORT)
|
||||||
|
|||||||
@@ -20,9 +20,11 @@
|
|||||||
#include "piiodevice.h"
|
#include "piiodevice.h"
|
||||||
|
|
||||||
#include "piconfig.h"
|
#include "piconfig.h"
|
||||||
#include "piconnection.h"
|
#include "piliterals_bytes.h"
|
||||||
#include "piliterals.h"
|
#include "piliterals_string.h"
|
||||||
|
#include "piliterals_time.h"
|
||||||
#include "pipropertystorage.h"
|
#include "pipropertystorage.h"
|
||||||
|
#include "pitime.h"
|
||||||
|
|
||||||
|
|
||||||
//! \class PIIODevice piiodevice.h
|
//! \class PIIODevice piiodevice.h
|
||||||
@@ -158,9 +160,9 @@ void PIIODevice::setReopenEnabled(bool yes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIIODevice::setReopenTimeout(int msecs) {
|
void PIIODevice::setReopenTimeout(PISystemTime timeout) {
|
||||||
setProperty("reopenTimeout", msecs);
|
setProperty("reopenTimeout", timeout);
|
||||||
reopen_timeout = msecs;
|
reopen_timeout = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -231,11 +233,13 @@ void PIIODevice::terminateThreadedRead() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIIODevice::waitThreadedReadFinished(int timeout_ms) {
|
bool PIIODevice::waitThreadedReadFinished(PISystemTime timeout) {
|
||||||
PITimeMeasurer tm, tm_intr;
|
PITimeMeasurer tm, tm_intr;
|
||||||
while (read_thread.isRunning()) {
|
while (read_thread.isRunning()) {
|
||||||
if (tm.elapsed_m() > timeout_ms) return false;
|
if (timeout.isNotNull()) {
|
||||||
if (tm_intr.elapsed_m() > 100.) {
|
if (tm.elapsed() > timeout) return false;
|
||||||
|
}
|
||||||
|
if (tm_intr.elapsed() > 100_ms) {
|
||||||
tm_intr.reset();
|
tm_intr.reset();
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
@@ -266,8 +270,8 @@ void PIIODevice::terminateThreadedWrite() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIIODevice::waitThreadedWriteFinished(int timeout_ms) {
|
bool PIIODevice::waitThreadedWriteFinished(PISystemTime timeout) {
|
||||||
return write_thread.waitForFinish(timeout_ms);
|
return write_thread.waitForFinish(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -290,10 +294,10 @@ void PIIODevice::stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIIODevice::stopAndWait(int timeout_ms) {
|
void PIIODevice::stopAndWait(PISystemTime timeout) {
|
||||||
stop();
|
stop();
|
||||||
waitThreadedReadFinished(timeout_ms);
|
waitThreadedReadFinished(timeout);
|
||||||
waitThreadedWriteFinished(timeout_ms);
|
waitThreadedWriteFinished(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -327,7 +331,7 @@ void PIIODevice::_init() {
|
|||||||
opened_ = false;
|
opened_ = false;
|
||||||
setOptions(0);
|
setOptions(0);
|
||||||
setReopenEnabled(true);
|
setReopenEnabled(true);
|
||||||
setReopenTimeout(1000);
|
setReopenTimeout(1_s);
|
||||||
#ifdef MICRO_PIP
|
#ifdef MICRO_PIP
|
||||||
threaded_read_buffer_size = 512;
|
threaded_read_buffer_size = 512;
|
||||||
#else
|
#else
|
||||||
@@ -375,7 +379,7 @@ void PIIODevice::read_func() {
|
|||||||
piMSleep(10);
|
piMSleep(10);
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
if (reopen_enabled) {
|
if (reopen_enabled) {
|
||||||
if (reopen_tm.elapsed_m() >= reopen_timeout) {
|
if (reopen_tm.elapsed() >= reopen_timeout) {
|
||||||
reopen_tm.reset();
|
reopen_tm.reset();
|
||||||
ok = open();
|
ok = open();
|
||||||
}
|
}
|
||||||
@@ -394,14 +398,14 @@ void PIIODevice::read_func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIByteArray PIIODevice::readForTime(double timeout_ms) {
|
PIByteArray PIIODevice::readForTime(PISystemTime timeout) {
|
||||||
PIByteArray str;
|
PIByteArray str;
|
||||||
if (timeout_ms <= 0.) return str;
|
if (timeout.isNull()) return str;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
uchar * td = new uchar[threaded_read_buffer_size];
|
uchar * td = new uchar[threaded_read_buffer_size];
|
||||||
bool was_br = setOption(BlockingRead, false);
|
bool was_br = setOption(BlockingRead, false);
|
||||||
tm.reset();
|
tm.reset();
|
||||||
while (tm.elapsed_m() < timeout_ms) {
|
while (tm.elapsed() < timeout) {
|
||||||
ret = read(td, threaded_read_buffer_size);
|
ret = read(td, threaded_read_buffer_size);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
piMinSleep();
|
piMinSleep();
|
||||||
@@ -477,13 +481,13 @@ bool PIIODevice::configure(const PIString & config_file, const PIString & sectio
|
|||||||
if (ep != 0) {
|
if (ep != 0) {
|
||||||
setReopenEnabled(ep->getValue("reopenEnabled", isReopenEnabled(), &ex).toBool());
|
setReopenEnabled(ep->getValue("reopenEnabled", isReopenEnabled(), &ex).toBool());
|
||||||
if (!ex) setReopenEnabled(em.getValue("reopenEnabled", isReopenEnabled()).toBool());
|
if (!ex) setReopenEnabled(em.getValue("reopenEnabled", isReopenEnabled()).toBool());
|
||||||
setReopenTimeout(ep->getValue("reopenTimeout", reopenTimeout(), &ex).toInt());
|
setReopenTimeout(PISystemTime::fromMilliseconds(ep->getValue("reopenTimeout", reopenTimeout().toMilliseconds(), &ex).toInt()));
|
||||||
if (!ex) setReopenTimeout(em.getValue("reopenTimeout", reopenTimeout()).toInt());
|
if (!ex) setReopenTimeout(PISystemTime::fromMilliseconds(em.getValue("reopenTimeout", reopenTimeout().toMilliseconds()).toInt()));
|
||||||
setThreadedReadBufferSize(ep->getValue("threadedReadBufferSize", int(threaded_read_buffer_size), &ex).toInt());
|
setThreadedReadBufferSize(ep->getValue("threadedReadBufferSize", int(threaded_read_buffer_size), &ex).toInt());
|
||||||
if (!ex) setThreadedReadBufferSize(em.getValue("threadedReadBufferSize", int(threaded_read_buffer_size)).toInt());
|
if (!ex) setThreadedReadBufferSize(em.getValue("threadedReadBufferSize", int(threaded_read_buffer_size)).toInt());
|
||||||
} else {
|
} else {
|
||||||
setReopenEnabled(em.getValue("reopenEnabled", isReopenEnabled()).toBool());
|
setReopenEnabled(em.getValue("reopenEnabled", isReopenEnabled()).toBool());
|
||||||
setReopenTimeout(em.getValue("reopenTimeout", reopenTimeout()).toInt());
|
setReopenTimeout(PISystemTime::fromMilliseconds(em.getValue("reopenTimeout", reopenTimeout().toMilliseconds()).toInt()));
|
||||||
setThreadedReadBufferSize(em.getValue("threadedReadBufferSize", int(threaded_read_buffer_size)).toInt());
|
setThreadedReadBufferSize(em.getValue("threadedReadBufferSize", int(threaded_read_buffer_size)).toInt());
|
||||||
}
|
}
|
||||||
return configureDevice(&em, ep);
|
return configureDevice(&em, ep);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include "piinit.h"
|
#include "piinit.h"
|
||||||
#include "piqueue.h"
|
#include "piqueue.h"
|
||||||
#include "pitimer.h"
|
#include "pithread.h"
|
||||||
|
|
||||||
/// TODO: написать документацию, тут ничего не понятно
|
/// TODO: написать документацию, тут ничего не понятно
|
||||||
// function executed from threaded read, pass readedData, sizeOfData, ThreadedReadData
|
// function executed from threaded read, pass readedData, sizeOfData, ThreadedReadData
|
||||||
@@ -201,21 +201,17 @@ public:
|
|||||||
//! \~russian Устанавливает возможность вызова \a open() при потоковом чтении на закрытом устройстве
|
//! \~russian Устанавливает возможность вызова \a open() при потоковом чтении на закрытом устройстве
|
||||||
void setReopenEnabled(bool yes = true);
|
void setReopenEnabled(bool yes = true);
|
||||||
|
|
||||||
//! \~english Set timeout in milliseconds between \a open() tryings if reopen is enabled
|
|
||||||
//! \~russian Устанавливает задержку в миллисекундах между вызовами \a open() если переоткрытие активно
|
|
||||||
void setReopenTimeout(int msecs);
|
|
||||||
|
|
||||||
//! \~english Set timeout between \a open() tryings if reopen is enabled
|
//! \~english Set timeout between \a open() tryings if reopen is enabled
|
||||||
//! \~russian Устанавливает задержку между вызовами \a open() если переоткрытие активно
|
//! \~russian Устанавливает задержку между вызовами \a open() если переоткрытие активно
|
||||||
void setReopenTimeout(PISystemTime timeout) { setReopenTimeout(timeout.toMilliseconds()); }
|
void setReopenTimeout(PISystemTime timeout);
|
||||||
|
|
||||||
//! \~english Returns reopen enable
|
//! \~english Returns reopen enable
|
||||||
//! \~russian Возвращает активно ли переоткрытие
|
//! \~russian Возвращает активно ли переоткрытие
|
||||||
bool isReopenEnabled() const { return property("reopenEnabled").toBool(); }
|
bool isReopenEnabled() const { return property("reopenEnabled").toBool(); }
|
||||||
|
|
||||||
//! \~english Returns reopen timeout in milliseconds
|
//! \~english Returns reopen timeout
|
||||||
//! \~russian Возвращает задержку переоткрытия в миллисекундах
|
//! \~russian Возвращает задержку переоткрытия
|
||||||
int reopenTimeout() { return property("reopenTimeout").toInt(); }
|
PISystemTime reopenTimeout() { return property("reopenTimeout").toSystemTime(); }
|
||||||
|
|
||||||
|
|
||||||
//! \~english Set threaded read callback
|
//! \~english Set threaded read callback
|
||||||
@@ -266,13 +262,9 @@ public:
|
|||||||
//! \~russian Старайтесь не использовать! Этот метод может привести к повреждению памяти!
|
//! \~russian Старайтесь не использовать! Этот метод может привести к повреждению памяти!
|
||||||
void terminateThreadedRead();
|
void terminateThreadedRead();
|
||||||
|
|
||||||
//! \~english Wait for threaded read finish no longer than "timeout_ms" milliseconds.
|
|
||||||
//! \~russian Ожидает завершения потокового чтения в течении не более "timeout_ms" миллисекунд.
|
|
||||||
bool waitThreadedReadFinished(int timeout_ms = -1);
|
|
||||||
|
|
||||||
//! \~english Wait for threaded read finish no longer than "timeout".
|
//! \~english Wait for threaded read finish no longer than "timeout".
|
||||||
//! \~russian Ожидает завершения потокового чтения в течении не более "timeout".
|
//! \~russian Ожидает завершения потокового чтения в течении не более "timeout".
|
||||||
bool waitThreadedReadFinished(PISystemTime timeout) { return waitThreadedReadFinished(timeout.toMilliseconds()); }
|
bool waitThreadedReadFinished(PISystemTime timeout = {});
|
||||||
|
|
||||||
|
|
||||||
//! \~english Returns if threaded write is started
|
//! \~english Returns if threaded write is started
|
||||||
@@ -294,13 +286,9 @@ public:
|
|||||||
//! \~russian Старайтесь не использовать! Этот метод может привести к повреждению памяти!
|
//! \~russian Старайтесь не использовать! Этот метод может привести к повреждению памяти!
|
||||||
void terminateThreadedWrite();
|
void terminateThreadedWrite();
|
||||||
|
|
||||||
//! \~english Wait for threaded write finish no longer than "timeout_ms" milliseconds.
|
|
||||||
//! \~russian Ожидает завершения потоковой записи в течении не более "timeout_ms" миллисекунд.
|
|
||||||
bool waitThreadedWriteFinished(int timeout_ms = -1);
|
|
||||||
|
|
||||||
//! \~english Wait for threaded write finish no longer than "timeout".
|
//! \~english Wait for threaded write finish no longer than "timeout".
|
||||||
//! \~russian Ожидает завершения потоковой записи в течении не более "timeout".
|
//! \~russian Ожидает завершения потоковой записи в течении не более "timeout".
|
||||||
bool waitThreadedWriteFinished(PISystemTime timeout) { return waitThreadedWriteFinished(timeout.toMilliseconds()); }
|
bool waitThreadedWriteFinished(PISystemTime timeout = {});
|
||||||
|
|
||||||
//! \~english Clear threaded write task queue
|
//! \~english Clear threaded write task queue
|
||||||
//! \~russian Очищает очередь потоковой записи
|
//! \~russian Очищает очередь потоковой записи
|
||||||
@@ -317,11 +305,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Stop both threaded read and threaded write and wait for finish.
|
//! \~english Stop both threaded read and threaded write and wait for finish.
|
||||||
//! \~russian Останавливает потоковое чтение и запись и ожидает завершения.
|
//! \~russian Останавливает потоковое чтение и запись и ожидает завершения.
|
||||||
void stopAndWait(int timeout_ms = -1);
|
void stopAndWait(PISystemTime timeout = {});
|
||||||
|
|
||||||
//! \~english Stop both threaded read and threaded write and wait for finish.
|
|
||||||
//! \~russian Останавливает потоковое чтение и запись и ожидает завершения.
|
|
||||||
void stopAndWait(PISystemTime timeout) { return stopAndWait(timeout.toMilliseconds()); }
|
|
||||||
|
|
||||||
//! \~english Interrupt blocking operation.
|
//! \~english Interrupt blocking operation.
|
||||||
//! \~russian Прерывает блокирующую операцию.
|
//! \~russian Прерывает блокирующую операцию.
|
||||||
@@ -355,15 +339,9 @@ public:
|
|||||||
//! \~russian Пишет в устройство не более "max_size" байт из "data"
|
//! \~russian Пишет в устройство не более "max_size" байт из "data"
|
||||||
ssize_t write(const void * data, ssize_t max_size);
|
ssize_t write(const void * data, ssize_t max_size);
|
||||||
|
|
||||||
//! \~english Read from device for "timeout_ms" milliseconds and return readed data as PIByteArray.
|
|
||||||
//! Timeout should to be greater than 0
|
|
||||||
//! \~russian Читает из устройства в течении "timeout_ms" миллисекунд и возвращает данные как PIByteArray.
|
|
||||||
//! Таймаут должен быть больше 0
|
|
||||||
PIByteArray readForTime(double timeout_ms);
|
|
||||||
|
|
||||||
//! \~english Read from device for "timeout" and return readed data as PIByteArray.
|
//! \~english Read from device for "timeout" and return readed data as PIByteArray.
|
||||||
//! \~russian Читает из устройства в течении "timeout" и возвращает данные как PIByteArray.
|
//! \~russian Читает из устройства в течении "timeout" и возвращает данные как PIByteArray.
|
||||||
PIByteArray readForTime(PISystemTime timeout) { return readForTime(timeout.toMilliseconds()); }
|
PIByteArray readForTime(PISystemTime timeout);
|
||||||
|
|
||||||
|
|
||||||
//! \~english Add task to threaded write queue and return task ID
|
//! \~english Add task to threaded write queue and return task ID
|
||||||
@@ -506,8 +484,8 @@ public:
|
|||||||
//! \~russian setReopenEnabled, по умолчанию "true"
|
//! \~russian setReopenEnabled, по умолчанию "true"
|
||||||
bool reopenEnabled;
|
bool reopenEnabled;
|
||||||
|
|
||||||
//! \~english setReopenTimeout in milliseconds, default 1000
|
//! \~english setReopenTimeout, default 1_s
|
||||||
//! \~russian setReopenTimeout в миллисекундах, по умолчанию 1000
|
//! \~russian setReopenTimeout, по умолчанию 1_s
|
||||||
int reopenTimeout;
|
int reopenTimeout;
|
||||||
|
|
||||||
//! \~english setThreadedReadBufferSize in bytes, default 4096
|
//! \~english setThreadedReadBufferSize in bytes, default 4096
|
||||||
@@ -609,8 +587,9 @@ private:
|
|||||||
PIThread read_thread, write_thread;
|
PIThread read_thread, write_thread;
|
||||||
PIByteArray buffer_in, buffer_tr;
|
PIByteArray buffer_in, buffer_tr;
|
||||||
PIQueue<PIPair<PIByteArray, ullong>> write_queue;
|
PIQueue<PIPair<PIByteArray, ullong>> write_queue;
|
||||||
|
PISystemTime reopen_timeout;
|
||||||
ullong tri = 0;
|
ullong tri = 0;
|
||||||
uint threaded_read_buffer_size, reopen_timeout = 1000;
|
uint threaded_read_buffer_size;
|
||||||
bool reopen_enabled = true, destroying = false;
|
bool reopen_enabled = true, destroying = false;
|
||||||
|
|
||||||
static PIMutex nfp_mutex;
|
static PIMutex nfp_mutex;
|
||||||
|
|||||||
@@ -21,7 +21,9 @@
|
|||||||
|
|
||||||
#include "piconfig.h"
|
#include "piconfig.h"
|
||||||
#include "pidatatransfer.h"
|
#include "pidatatransfer.h"
|
||||||
|
#include "piliterals_time.h"
|
||||||
#include "pipropertystorage.h"
|
#include "pipropertystorage.h"
|
||||||
|
#include "pitime.h"
|
||||||
|
|
||||||
#define _PIPEER_MSG_SIZE 4000
|
#define _PIPEER_MSG_SIZE 4000
|
||||||
#define _PIPEER_MSG_TTL 100
|
#define _PIPEER_MSG_TTL 100
|
||||||
@@ -85,7 +87,7 @@ PIPeer::PeerData::~PeerData() {
|
|||||||
dt_in.stop();
|
dt_in.stop();
|
||||||
dt_out.stop();
|
dt_out.stop();
|
||||||
t.stop();
|
t.stop();
|
||||||
if (!t.waitForFinish(1000)) t.terminate();
|
if (!t.waitForFinish(1_s)) t.terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -182,12 +184,12 @@ PIPeer::PIPeer(const PIString & n)
|
|||||||
PIMutexLocker pl(peers_mutex);
|
PIMutexLocker pl(peers_mutex);
|
||||||
PIMutexLocker sl(send_mutex);
|
PIMutexLocker sl(send_mutex);
|
||||||
changeName(n);
|
changeName(n);
|
||||||
setReopenTimeout(100);
|
setReopenTimeout(100_ms);
|
||||||
read_buffer_size = 128;
|
read_buffer_size = 128;
|
||||||
self_info.dist = 0;
|
self_info.dist = 0;
|
||||||
self_info.time = PISystemTime::current();
|
self_info.time = PISystemTime::current();
|
||||||
randomize();
|
randomize();
|
||||||
CONNECT2(void, void *, int, &sync_timer, tickEvent, this, timerEvent);
|
CONNECT1(void, int, &sync_timer, tickEvent, this, timerEvent);
|
||||||
prev_ifaces = PIEthernet::interfaces();
|
prev_ifaces = PIEthernet::interfaces();
|
||||||
no_timer = false;
|
no_timer = false;
|
||||||
sync_timer.addDelimiter(5);
|
sync_timer.addDelimiter(5);
|
||||||
@@ -199,9 +201,9 @@ PIPeer::~PIPeer() {
|
|||||||
stop();
|
stop();
|
||||||
if (destroyed) return;
|
if (destroyed) return;
|
||||||
destroyed = true;
|
destroyed = true;
|
||||||
sync_timer.stop();
|
sync_timer.stopAndWait();
|
||||||
diag_s.stop();
|
diag_s.stopAndWait();
|
||||||
diag_d.stop();
|
diag_d.stopAndWait();
|
||||||
PIMutexLocker ml(peers_mutex);
|
PIMutexLocker ml(peers_mutex);
|
||||||
piForeach(PeerInfo & p, peers)
|
piForeach(PeerInfo & p, peers)
|
||||||
if (p._data) {
|
if (p._data) {
|
||||||
@@ -212,15 +214,15 @@ PIPeer::~PIPeer() {
|
|||||||
destroyEths();
|
destroyEths();
|
||||||
piForeach(PIEthernet * i, eths_mcast) {
|
piForeach(PIEthernet * i, eths_mcast) {
|
||||||
if (!i) continue;
|
if (!i) continue;
|
||||||
i->stopThreadedRead();
|
i->stopAndWait();
|
||||||
}
|
}
|
||||||
piForeach(PIEthernet * i, eths_bcast) {
|
piForeach(PIEthernet * i, eths_bcast) {
|
||||||
if (!i) continue;
|
if (!i) continue;
|
||||||
i->stopThreadedRead();
|
i->stopAndWait();
|
||||||
}
|
}
|
||||||
eth_lo.stopThreadedRead();
|
eth_lo.stopAndWait();
|
||||||
eth_tcp_srv.stopThreadedRead();
|
eth_tcp_srv.stopAndWait();
|
||||||
eth_tcp_cli.stopThreadedRead();
|
eth_tcp_cli.stopAndWait();
|
||||||
sendSelfRemove();
|
sendSelfRemove();
|
||||||
destroyMBcasts();
|
destroyMBcasts();
|
||||||
eth_send.close();
|
eth_send.close();
|
||||||
@@ -229,7 +231,7 @@ PIPeer::~PIPeer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIPeer::timerEvent(void * data, int delim) {
|
void PIPeer::timerEvent(int delim) {
|
||||||
// piCoutObj << "timerEvent" << delim;
|
// piCoutObj << "timerEvent" << delim;
|
||||||
if (no_timer) return;
|
if (no_timer) return;
|
||||||
switch (delim) {
|
switch (delim) {
|
||||||
@@ -362,46 +364,32 @@ void PIPeer::initMBcasts(PIStringList al) {
|
|||||||
|
|
||||||
|
|
||||||
void PIPeer::destroyEths() {
|
void PIPeer::destroyEths() {
|
||||||
piForeach(PIEthernet * i, eths_traffic) {
|
for (auto * i: eths_traffic) {
|
||||||
if (!i) continue;
|
if (!i) continue;
|
||||||
((PIThread *)i)->stop();
|
i->stopAndWait();
|
||||||
((PIThread *)i)->waitForFinish(100);
|
|
||||||
i->stopThreadedRead();
|
|
||||||
i->close();
|
i->close();
|
||||||
delete i;
|
|
||||||
i = 0;
|
|
||||||
}
|
}
|
||||||
eths_traffic.clear();
|
piDeleteAllAndClear(eths_traffic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIPeer::destroyMBcasts() {
|
void PIPeer::destroyMBcasts() {
|
||||||
piForeach(PIEthernet * i, eths_mcast) {
|
for (auto * i: eths_mcast) {
|
||||||
if (!i) continue;
|
if (!i) continue;
|
||||||
((PIThread *)i)->stop();
|
|
||||||
((PIThread *)i)->waitForFinish(100);
|
|
||||||
i->stopThreadedRead();
|
|
||||||
i->leaveMulticastGroup(_PIPEER_MULTICAST_IP);
|
i->leaveMulticastGroup(_PIPEER_MULTICAST_IP);
|
||||||
|
i->stopAndWait();
|
||||||
i->close();
|
i->close();
|
||||||
delete i;
|
|
||||||
i = 0;
|
|
||||||
}
|
}
|
||||||
eths_mcast.clear();
|
for (auto * i: eths_bcast) {
|
||||||
piForeach(PIEthernet * i, eths_bcast) {
|
|
||||||
if (!i) continue;
|
if (!i) continue;
|
||||||
((PIThread *)i)->stop();
|
i->stopAndWait();
|
||||||
((PIThread *)i)->waitForFinish(100);
|
|
||||||
i->stopThreadedRead();
|
|
||||||
i->close();
|
i->close();
|
||||||
delete i;
|
|
||||||
i = 0;
|
|
||||||
}
|
}
|
||||||
eths_bcast.clear();
|
piDeleteAllAndClear(eths_mcast);
|
||||||
((PIThread *)ð_lo)->stop();
|
piDeleteAllAndClear(eths_bcast);
|
||||||
((PIThread *)ð_lo)->waitForFinish(100);
|
eth_lo.stopAndWait();
|
||||||
eth_lo.stopThreadedRead();
|
|
||||||
eth_lo.close();
|
eth_lo.close();
|
||||||
eth_tcp_srv.stop();
|
eth_tcp_srv.stopAndWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -918,7 +906,7 @@ void PIPeer::reinit() {
|
|||||||
initNetwork();
|
initNetwork();
|
||||||
sendSelfInfo();
|
sendSelfInfo();
|
||||||
no_timer = false;
|
no_timer = false;
|
||||||
if (!sync_timer.isRunning()) sync_timer.start(1000);
|
if (!sync_timer.isRunning()) sync_timer.start(1_Hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ protected:
|
|||||||
EVENT_HANDLER2(bool, mbcastRead, const uchar *, readed, ssize_t, size);
|
EVENT_HANDLER2(bool, mbcastRead, const uchar *, readed, ssize_t, size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EVENT_HANDLER2(void, timerEvent, void *, data, int, delim);
|
EVENT_HANDLER1(void, timerEvent, int, delim);
|
||||||
EVENT_HANDLER2(bool, sendInternal, const PIString &, to, const PIByteArray &, data);
|
EVENT_HANDLER2(bool, sendInternal, const PIString &, to, const PIByteArray &, data);
|
||||||
EVENT_HANDLER2(void, dtReceived, const PIString &, from, const PIByteArray &, data);
|
EVENT_HANDLER2(void, dtReceived, const PIString &, from, const PIByteArray &, data);
|
||||||
EVENT_HANDLER1(void, newTcpClient, PIEthernet *, client);
|
EVENT_HANDLER1(void, newTcpClient, PIEthernet *, client);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "pidir.h"
|
#include "pidir.h"
|
||||||
#include "piincludes_p.h"
|
#include "piincludes_p.h"
|
||||||
#include "pipropertystorage.h"
|
#include "pipropertystorage.h"
|
||||||
|
#include "pitime.h"
|
||||||
#include "piwaitevent_p.h"
|
#include "piwaitevent_p.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
#include "pibasetransfer.h"
|
#include "pibasetransfer.h"
|
||||||
|
|
||||||
|
#include "pitime.h"
|
||||||
|
|
||||||
const uint PIBaseTransfer::signature = 0x54424950;
|
const uint PIBaseTransfer::signature = 0x54424950;
|
||||||
|
|
||||||
PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()), diag(false) {
|
PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()), diag(false) {
|
||||||
@@ -33,7 +35,7 @@ PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()), diag(false) {
|
|||||||
send_queue = 0;
|
send_queue = 0;
|
||||||
send_up = 0;
|
send_up = 0;
|
||||||
timeout_ = 10.;
|
timeout_ = 10.;
|
||||||
diag.setDisconnectTimeout(timeout_ / 10);
|
diag.setDisconnectTimeout(PISystemTime::fromSeconds(timeout_ / 10.));
|
||||||
diag.setName("PIBaseTransfer");
|
diag.setName("PIBaseTransfer");
|
||||||
diag.start(50);
|
diag.start(50);
|
||||||
packets_count = 10;
|
packets_count = 10;
|
||||||
@@ -47,7 +49,7 @@ PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()), diag(false) {
|
|||||||
|
|
||||||
|
|
||||||
PIBaseTransfer::~PIBaseTransfer() {
|
PIBaseTransfer::~PIBaseTransfer() {
|
||||||
diag.stop();
|
diag.stopAndWait();
|
||||||
break_ = true;
|
break_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +79,12 @@ void PIBaseTransfer::setPause(bool pause_) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIBaseTransfer::setTimeout(double sec) {
|
||||||
|
timeout_ = sec;
|
||||||
|
diag.setDisconnectTimeout(PISystemTime::fromSeconds(sec));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIBaseTransfer::received(PIByteArray data) {
|
void PIBaseTransfer::received(PIByteArray data) {
|
||||||
packet_header_size = sizeof(PacketHeader) + customHeader().size();
|
packet_header_size = sizeof(PacketHeader) + customHeader().size();
|
||||||
if (data.size() < sizeof(PacketHeader)) {
|
if (data.size() < sizeof(PacketHeader)) {
|
||||||
|
|||||||
@@ -65,10 +65,7 @@ public:
|
|||||||
void setPacketSize(int size) { packet_size = size; }
|
void setPacketSize(int size) { packet_size = size; }
|
||||||
int packetSize() const { return packet_size; }
|
int packetSize() const { return packet_size; }
|
||||||
|
|
||||||
void setTimeout(double sec) {
|
void setTimeout(double sec);
|
||||||
timeout_ = sec;
|
|
||||||
diag.setDisconnectTimeout(sec);
|
|
||||||
}
|
|
||||||
double timeout() const { return timeout_; }
|
double timeout() const { return timeout_; }
|
||||||
|
|
||||||
void setCRCEnabled(bool en = true) { crc_enabled = en; }
|
void setCRCEnabled(bool en = true) { crc_enabled = en; }
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include "piconfig.h"
|
#include "piconfig.h"
|
||||||
#include "piiostream.h"
|
#include "piiostream.h"
|
||||||
|
#include "piliterals_time.h"
|
||||||
|
#include "pitime.h"
|
||||||
|
|
||||||
/** \class PIConnection
|
/** \class PIConnection
|
||||||
* \brief Complex Input/Output point
|
* \brief Complex Input/Output point
|
||||||
@@ -160,7 +162,9 @@ bool PIConnection::configure(PIConfig & conf, const PIString & name_) {
|
|||||||
PIConfig::Entry de = ce.getValue("device." + n);
|
PIConfig::Entry de = ce.getValue("device." + n);
|
||||||
dev->setThreadedReadBufferSize(de.getValue("bufferSize", dev->threadedReadBufferSize()).toInt());
|
dev->setThreadedReadBufferSize(de.getValue("bufferSize", dev->threadedReadBufferSize()).toInt());
|
||||||
PIDiagnostics * diag = diags_.value(dev, nullptr);
|
PIDiagnostics * diag = diags_.value(dev, nullptr);
|
||||||
if (diag) diag->setDisconnectTimeout(de.getValue("disconnectTimeout", diag->disconnectTimeout()).toFloat());
|
if (diag)
|
||||||
|
diag->setDisconnectTimeout(
|
||||||
|
PISystemTime::fromSeconds(de.getValue("disconnectTimeout", diag->disconnectTimeout().toSeconds()).toFloat()));
|
||||||
}
|
}
|
||||||
int added(0), padded(-1), tries(0);
|
int added(0), padded(-1), tries(0);
|
||||||
bool pdebug = debug();
|
bool pdebug = debug();
|
||||||
@@ -223,9 +227,11 @@ bool PIConnection::configure(PIConfig & conf, const PIString & name_) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
PIDiagnostics * diag = diags_.value(pe, nullptr);
|
PIDiagnostics * diag = diags_.value(pe, nullptr);
|
||||||
if (diag) diag->setDisconnectTimeout(e->getValue("disconnectTimeout", diag->disconnectTimeout()).toFloat());
|
if (diag)
|
||||||
|
diag->setDisconnectTimeout(
|
||||||
|
PISystemTime::fromSeconds(e->getValue("disconnectTimeout", diag->disconnectTimeout().toSeconds()).toFloat()));
|
||||||
pe->setPayloadSize(e->getValue("payloadSize", pe->payloadSize()).toInt());
|
pe->setPayloadSize(e->getValue("payloadSize", pe->payloadSize()).toInt());
|
||||||
pe->setTimeout(e->getValue("timeout", pe->timeout()).toDouble());
|
pe->setTimeout(PISystemTime::fromMilliseconds(e->getValue("timeout", pe->timeout().toMilliseconds()).toDouble()));
|
||||||
pe->setHeader(PIByteArray::fromUserInput(e->getValue("header", "").toString()));
|
pe->setHeader(PIByteArray::fromUserInput(e->getValue("header", "").toString()));
|
||||||
pe->setFooter(PIByteArray::fromUserInput(e->getValue("footer", "").toString()));
|
pe->setFooter(PIByteArray::fromUserInput(e->getValue("footer", "").toString()));
|
||||||
}
|
}
|
||||||
@@ -271,7 +277,7 @@ PIString PIConnection::makeConfig() const {
|
|||||||
ts << "device." << dname << " = " << d->constructFullPath() << " #s\n";
|
ts << "device." << dname << " = " << d->constructFullPath() << " #s\n";
|
||||||
ts << "device." << dname << ".bufferSize = " << d->threadedReadBufferSize() << " #n\n";
|
ts << "device." << dname << ".bufferSize = " << d->threadedReadBufferSize() << " #n\n";
|
||||||
PIDiagnostics * diag = diags_.value(const_cast<PIIODevice *>(d), nullptr);
|
PIDiagnostics * diag = diags_.value(const_cast<PIIODevice *>(d), nullptr);
|
||||||
if (diag) ts << "device." << dname << ".disconnectTimeout = " << diag->disconnectTimeout() << " #f\n";
|
if (diag) ts << "device." << dname << ".disconnectTimeout = " << diag->disconnectTimeout().toSeconds() << " #f\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto ite = extractors.makeIterator();
|
auto ite = extractors.makeIterator();
|
||||||
@@ -285,7 +291,7 @@ PIString PIConnection::makeConfig() const {
|
|||||||
ts << prefix << ".device." << i << " = " << dname << " #s\n";
|
ts << prefix << ".device." << i << " = " << dname << " #s\n";
|
||||||
}
|
}
|
||||||
PIDiagnostics * diag = diags_.value(ite.value()->extractor, nullptr);
|
PIDiagnostics * diag = diags_.value(ite.value()->extractor, nullptr);
|
||||||
if (diag) ts << prefix << ".disconnectTimeout = " << diag->disconnectTimeout() << " #f\n";
|
if (diag) ts << prefix << ".disconnectTimeout = " << diag->disconnectTimeout().toSeconds() << " #f\n";
|
||||||
ts << prefix << ".splitMode = ";
|
ts << prefix << ".splitMode = ";
|
||||||
switch (ite.value()->extractor->splitMode()) {
|
switch (ite.value()->extractor->splitMode()) {
|
||||||
case PIPacketExtractor::None: ts << "none"; break;
|
case PIPacketExtractor::None: ts << "none"; break;
|
||||||
@@ -297,7 +303,7 @@ PIString PIConnection::makeConfig() const {
|
|||||||
}
|
}
|
||||||
ts << " #s\n";
|
ts << " #s\n";
|
||||||
ts << prefix << ".payloadSize = " << ite.value()->extractor->payloadSize() << " #n\n";
|
ts << prefix << ".payloadSize = " << ite.value()->extractor->payloadSize() << " #n\n";
|
||||||
ts << prefix << ".timeout = " << ite.value()->extractor->timeout() << " #f\n";
|
ts << prefix << ".timeout = " << ite.value()->extractor->timeout().toMilliseconds() << " #f\n";
|
||||||
ts << prefix << ".header = " << ite.value()->extractor->header().toString() << " #s\n";
|
ts << prefix << ".header = " << ite.value()->extractor->header().toString() << " #s\n";
|
||||||
ts << prefix << ".footer = " << ite.value()->extractor->footer().toString() << " #s\n";
|
ts << prefix << ".footer = " << ite.value()->extractor->footer().toString() << " #s\n";
|
||||||
}
|
}
|
||||||
@@ -324,8 +330,8 @@ PIString PIConnection::makeConfig() const {
|
|||||||
if (dname.isEmpty()) dname = devPath(its.value()->devices[i]);
|
if (dname.isEmpty()) dname = devPath(its.value()->devices[i]);
|
||||||
ts << prefix << ".device." << i << " = " << dname << " #s\n";
|
ts << prefix << ".device." << i << " = " << dname << " #s\n";
|
||||||
}
|
}
|
||||||
double int_ = its.value()->int_;
|
auto int_ = its.value()->int_;
|
||||||
if (int_ > 0.) ts << prefix << ".frequency = " << (1000. / int_) << " #f\n";
|
if (!int_.isNull()) ts << prefix << ".frequency = " << (1. / int_.toSeconds()) << " #f\n";
|
||||||
if (!its.value()->sdata.isEmpty()) ts << prefix << ".fixedData = " << its.value()->sdata.toString() << " #s\n";
|
if (!its.value()->sdata.isEmpty()) ts << prefix << ".fixedData = " << its.value()->sdata.toString() << " #s\n";
|
||||||
}
|
}
|
||||||
ts << "[]\n";
|
ts << "[]\n";
|
||||||
@@ -342,7 +348,7 @@ PIIODevice * PIConnection::addDevice(const PIString & full_path, PIIODevice::Dev
|
|||||||
__device_pool__->lock();
|
__device_pool__->lock();
|
||||||
if (!diags_.value(dev, nullptr)) {
|
if (!diags_.value(dev, nullptr)) {
|
||||||
PIDiagnostics * d = new PIDiagnostics(false);
|
PIDiagnostics * d = new PIDiagnostics(false);
|
||||||
d->setInterval(100.);
|
d->setInterval(10_Hz);
|
||||||
diags_[dev] = d;
|
diags_[dev] = d;
|
||||||
CONNECT2(void, PIDiagnostics::Quality, PIDiagnostics::Quality, d, qualityChanged, this, diagQualityChanged);
|
CONNECT2(void, PIDiagnostics::Quality, PIDiagnostics::Quality, d, qualityChanged, this, diagQualityChanged);
|
||||||
__device_pool__->init();
|
__device_pool__->init();
|
||||||
@@ -476,7 +482,7 @@ PIPacketExtractor * PIConnection::addFilter(const PIString & name_, const PIStri
|
|||||||
__device_pool__->lock();
|
__device_pool__->lock();
|
||||||
if (!diags_.value(e->extractor, nullptr)) {
|
if (!diags_.value(e->extractor, nullptr)) {
|
||||||
PIDiagnostics * d = new PIDiagnostics(false);
|
PIDiagnostics * d = new PIDiagnostics(false);
|
||||||
d->setInterval(100.);
|
d->setInterval(10_Hz);
|
||||||
diags_[e->extractor] = d;
|
diags_[e->extractor] = d;
|
||||||
CONNECT2(void, PIDiagnostics::Quality, PIDiagnostics::Quality, d, qualityChanged, this, diagQualityChanged);
|
CONNECT2(void, PIDiagnostics::Quality, PIDiagnostics::Quality, d, qualityChanged, this, diagQualityChanged);
|
||||||
}
|
}
|
||||||
@@ -514,7 +520,7 @@ PIPacketExtractor * PIConnection::addFilter(PIPacketExtractor * filter, const PI
|
|||||||
__device_pool__->lock();
|
__device_pool__->lock();
|
||||||
if (diags_.value(e->extractor, 0) == 0) {
|
if (diags_.value(e->extractor, 0) == 0) {
|
||||||
PIDiagnostics * d = new PIDiagnostics(false);
|
PIDiagnostics * d = new PIDiagnostics(false);
|
||||||
d->setInterval(100.);
|
d->setInterval(10_Hz);
|
||||||
diags_[e->extractor] = d;
|
diags_[e->extractor] = d;
|
||||||
CONNECT2(void, PIDiagnostics::Quality, PIDiagnostics::Quality, d, qualityChanged, this, diagQualityChanged);
|
CONNECT2(void, PIDiagnostics::Quality, PIDiagnostics::Quality, d, qualityChanged, this, diagQualityChanged);
|
||||||
}
|
}
|
||||||
@@ -728,7 +734,7 @@ void PIConnection::addSender(const PIString & name_, const PIString & full_path_
|
|||||||
if (!s) {
|
if (!s) {
|
||||||
s = new Sender(this);
|
s = new Sender(this);
|
||||||
s->setName(fname_);
|
s->setName(fname_);
|
||||||
s->int_ = 1000. / frequency;
|
s->int_ = PISystemTime::fromSeconds(1. / frequency);
|
||||||
senders[fname_] = s;
|
senders[fname_] = s;
|
||||||
}
|
}
|
||||||
PIIODevice * dev = devByString(full_path_name);
|
PIIODevice * dev = devByString(full_path_name);
|
||||||
@@ -797,9 +803,9 @@ PIByteArray PIConnection::senderFixedData(const PIString & name) const {
|
|||||||
float PIConnection::senderFrequency(const PIString & name) const {
|
float PIConnection::senderFrequency(const PIString & name) const {
|
||||||
Sender * s = senders.value(name, nullptr);
|
Sender * s = senders.value(name, nullptr);
|
||||||
if (!s) return -1.f;
|
if (!s) return -1.f;
|
||||||
double i = s->interval();
|
auto i = s->interval();
|
||||||
if (i == 0.) return 0.f;
|
if (i.isNull()) return 0.f;
|
||||||
return 1000. / s->interval();
|
return 1. / s->interval().toSeconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -865,14 +871,14 @@ void PIConnection::stopAllThreadedReads() {
|
|||||||
void PIConnection::stopSender(const PIString & name) {
|
void PIConnection::stopSender(const PIString & name) {
|
||||||
Sender * s = senders.value(name, nullptr);
|
Sender * s = senders.value(name, nullptr);
|
||||||
if (!s) return;
|
if (!s) return;
|
||||||
if (s->isRunning()) s->stop();
|
if (s->isRunning()) s->stopAndWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIConnection::stopAllSenders() {
|
void PIConnection::stopAllSenders() {
|
||||||
for (auto s = senders.begin(); s != senders.end(); s++) {
|
for (auto s = senders.begin(); s != senders.end(); s++) {
|
||||||
if (!s.value()) continue;
|
if (!s.value()) continue;
|
||||||
if (s.value()->isRunning()) s.value()->stop();
|
if (s.value()->isRunning()) s.value()->stopAndWait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -949,7 +955,7 @@ bool PIConnection::isFakeMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIConnection::DevicePool::DevicePool(): PIThread(false, 10) {
|
PIConnection::DevicePool::DevicePool(): PIThread(false, 100_Hz) {
|
||||||
setName("PIConnection::DevicePool");
|
setName("PIConnection::DevicePool");
|
||||||
needLockRun(true);
|
needLockRun(true);
|
||||||
fake = false;
|
fake = false;
|
||||||
@@ -960,7 +966,7 @@ PIConnection::DevicePool::~DevicePool() {}
|
|||||||
|
|
||||||
|
|
||||||
void PIConnection::DevicePool::init() {
|
void PIConnection::DevicePool::init() {
|
||||||
if (!isRunning()) start(100);
|
if (!isRunning()) start(10_Hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1111,7 +1117,7 @@ PIConnection::DevicePool::DeviceData::~DeviceData() {
|
|||||||
if (rthread) {
|
if (rthread) {
|
||||||
rthread->stop();
|
rthread->stop();
|
||||||
if (dev) dev->interrupt();
|
if (dev) dev->interrupt();
|
||||||
if (!rthread->waitForFinish(1000)) rthread->terminate();
|
if (!rthread->waitForFinish(1_s)) rthread->terminate();
|
||||||
delete rthread;
|
delete rthread;
|
||||||
rthread = nullptr;
|
rthread = nullptr;
|
||||||
}
|
}
|
||||||
@@ -1128,7 +1134,7 @@ void PIConnection::DevicePool::run() {
|
|||||||
for (PIConnection * c: conns) {
|
for (PIConnection * c: conns) {
|
||||||
for (auto d = c->diags_.begin(); d != c->diags_.end(); d++) {
|
for (auto d = c->diags_.begin(); d != c->diags_.end(); d++) {
|
||||||
if (!d.value()) continue;
|
if (!d.value()) continue;
|
||||||
d.value()->tick(0, 1);
|
d.value()->tick(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1143,9 +1149,9 @@ void __DevicePool_threadReadDP(void * ddp) {
|
|||||||
}
|
}
|
||||||
if (dev->isClosed()) {
|
if (dev->isClosed()) {
|
||||||
if (!dev->open()) {
|
if (!dev->open()) {
|
||||||
|
auto timeout = dev->reopenTimeout();
|
||||||
PITimeMeasurer tm;
|
PITimeMeasurer tm;
|
||||||
int timeout = dev->reopenTimeout();
|
while (tm.elapsed() < timeout) {
|
||||||
while (tm.elapsed_m() < timeout) {
|
|
||||||
if (dd->rthread->isStopping()) return;
|
if (dd->rthread->isStopping()) return;
|
||||||
piMSleep(50);
|
piMSleep(50);
|
||||||
}
|
}
|
||||||
@@ -1204,13 +1210,13 @@ PIConnection::Extractor::~Extractor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIConnection::Sender::Sender(PIConnection * parent_): parent(parent_), int_(0.f) {
|
PIConnection::Sender::Sender(PIConnection * parent_): parent(parent_) {
|
||||||
setName("__S__.PIConnection.Sender");
|
setName("__S__.PIConnection.Sender");
|
||||||
needLockRun(true);
|
needLockRun(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIConnection::Sender::tick(void *, int) {
|
void PIConnection::Sender::tick(int) {
|
||||||
if (!parent) return;
|
if (!parent) return;
|
||||||
PIByteArray data;
|
PIByteArray data;
|
||||||
if (!sdata.isEmpty())
|
if (!sdata.isEmpty())
|
||||||
|
|||||||
@@ -387,12 +387,12 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Sender(PIConnection * parent_ = 0);
|
Sender(PIConnection * parent_ = 0);
|
||||||
~Sender() { stop(); }
|
~Sender() { stopAndWait(); }
|
||||||
PIConnection * parent;
|
PIConnection * parent;
|
||||||
PIVector<PIIODevice *> devices;
|
PIVector<PIIODevice *> devices;
|
||||||
PIByteArray sdata;
|
PIByteArray sdata;
|
||||||
float int_;
|
PISystemTime int_;
|
||||||
void tick(void *, int) override;
|
void tick(int) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
PIMap<PIString, Extractor *> extractors;
|
PIMap<PIString, Extractor *> extractors;
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
#include "pidiagnostics.h"
|
#include "pidiagnostics.h"
|
||||||
|
|
||||||
|
#include "piliterals_time.h"
|
||||||
|
|
||||||
|
|
||||||
/** \class PIDiagnostics
|
/** \class PIDiagnostics
|
||||||
* \brief Connection quality diagnostics
|
* \brief Connection quality diagnostics
|
||||||
@@ -42,18 +44,18 @@ PIDiagnostics::State::State() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIDiagnostics::PIDiagnostics(bool start_): PITimer(/*PITimer::Pool*/) {
|
PIDiagnostics::PIDiagnostics(bool start_): PITimer() {
|
||||||
// piCout << "PIDiagnostics construct";
|
// piCout << "PIDiagnostics construct";
|
||||||
setInterval(100);
|
setInterval(10_Hz);
|
||||||
reset();
|
reset();
|
||||||
setDisconnectTimeout(3.);
|
setDisconnectTimeout(3_s);
|
||||||
changeDisconnectTimeout(3.);
|
changeDisconnectTimeout(3_s);
|
||||||
if (start_) PITimer::start(100);
|
if (start_) PITimer::start(10_Hz);
|
||||||
// piCout << "PIDiagnostics construct done";
|
// piCout << "PIDiagnostics construct done";
|
||||||
}
|
}
|
||||||
|
|
||||||
PIDiagnostics::~PIDiagnostics() {
|
PIDiagnostics::~PIDiagnostics() {
|
||||||
PITimer::stop();
|
PITimer::stopAndWait();
|
||||||
// piCout << "~PIDiagnostics start...";
|
// piCout << "~PIDiagnostics start...";
|
||||||
// piCout << "~PIDiagnostics done!";
|
// piCout << "~PIDiagnostics done!";
|
||||||
}
|
}
|
||||||
@@ -92,14 +94,14 @@ PIString PIDiagnostics::sendSpeed() const {
|
|||||||
|
|
||||||
|
|
||||||
void PIDiagnostics::start() {
|
void PIDiagnostics::start() {
|
||||||
PITimer::start(100.);
|
PITimer::start(10_Hz);
|
||||||
changeDisconnectTimeout(disconn_);
|
changeDisconnectTimeout(disconn_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIDiagnostics::start(double msecs) {
|
void PIDiagnostics::start(double msecs) {
|
||||||
if (msecs > 0.) {
|
if (msecs > 0.) {
|
||||||
PITimer::start(msecs);
|
PITimer::start(PISystemTime::fromMilliseconds(msecs));
|
||||||
changeDisconnectTimeout(disconn_);
|
changeDisconnectTimeout(disconn_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,7 +110,7 @@ void PIDiagnostics::start(double msecs) {
|
|||||||
void PIDiagnostics::reset() {
|
void PIDiagnostics::reset() {
|
||||||
mutex_state.lock();
|
mutex_state.lock();
|
||||||
cur_state = State();
|
cur_state = State();
|
||||||
if (disconn_ != 0.) {
|
if (disconn_.isNotNull()) {
|
||||||
int hist_size = history_rec.size();
|
int hist_size = history_rec.size();
|
||||||
history_rec.clear();
|
history_rec.clear();
|
||||||
history_send.clear();
|
history_send.clear();
|
||||||
@@ -150,16 +152,16 @@ void PIDiagnostics::sended(int size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIDiagnostics::tick(void *, int) {
|
void PIDiagnostics::tick(int) {
|
||||||
mutex_state.lock();
|
mutex_state.lock();
|
||||||
// piCoutObj << "lock";
|
// piCoutObj << "lock";
|
||||||
int tcnt_recv = 0;
|
int tcnt_recv = 0;
|
||||||
int tcnt_send = 0;
|
int tcnt_send = 0;
|
||||||
Entry send = calcHistory(history_send, tcnt_send);
|
Entry send = calcHistory(history_send, tcnt_send);
|
||||||
Entry recv = calcHistory(history_rec, tcnt_recv);
|
Entry recv = calcHistory(history_rec, tcnt_recv);
|
||||||
float itr = disconn_ * (float(tcnt_recv) / history_rec.size());
|
float itr = disconn_.toSeconds() * (float(tcnt_recv) / history_rec.size());
|
||||||
float its = disconn_ * (float(tcnt_send) / history_send.size());
|
float its = disconn_.toSeconds() * (float(tcnt_send) / history_send.size());
|
||||||
float hz = interval() / 1000.f;
|
float hz = 1. / interval().toSeconds();
|
||||||
if (tcnt_recv == 0) {
|
if (tcnt_recv == 0) {
|
||||||
cur_state.integral_freq = cur_state.immediate_freq = 0;
|
cur_state.integral_freq = cur_state.immediate_freq = 0;
|
||||||
cur_state.received_packets_per_sec = cur_state.received_bytes_per_sec = 0;
|
cur_state.received_packets_per_sec = cur_state.received_bytes_per_sec = 0;
|
||||||
@@ -229,16 +231,15 @@ PIDiagnostics::Entry PIDiagnostics::calcHistory(PIQueue<Entry> & hist, int & cnt
|
|||||||
|
|
||||||
|
|
||||||
void PIDiagnostics::propertyChanged(const char *) {
|
void PIDiagnostics::propertyChanged(const char *) {
|
||||||
float disct = property("disconnectTimeout").toFloat();
|
changeDisconnectTimeout(property("disconnectTimeout").toSystemTime());
|
||||||
changeDisconnectTimeout(disct);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIDiagnostics::changeDisconnectTimeout(float disct) {
|
void PIDiagnostics::changeDisconnectTimeout(PISystemTime disct) {
|
||||||
mutex_state.lock();
|
mutex_state.lock();
|
||||||
disconn_ = piMaxf(disct, interval() / 1000.f);
|
disconn_ = piMax(disct, interval());
|
||||||
if (interval() > 0) {
|
if (!interval().isNull()) {
|
||||||
int hist_size = piClampi(int(disconn_ * 1000.f / float(interval())), 1, 65536);
|
int hist_size = piClampi(piRound(disconn_.toSeconds() / interval().toSeconds()), 1, 65536);
|
||||||
// piCoutObj << hist_size << interval();
|
// piCoutObj << hist_size << interval();
|
||||||
history_rec.resize(hist_size);
|
history_rec.resize(hist_size);
|
||||||
history_send.resize(hist_size);
|
history_send.resize(hist_size);
|
||||||
|
|||||||
@@ -75,13 +75,15 @@ public:
|
|||||||
PIDiagnostics::State state() const;
|
PIDiagnostics::State state() const;
|
||||||
|
|
||||||
//! Returns period of full disconnect in seconds and period of averaging frequency
|
//! Returns period of full disconnect in seconds and period of averaging frequency
|
||||||
float disconnectTimeout() const { return disconn_; }
|
PISystemTime disconnectTimeout() const { return disconn_; }
|
||||||
|
|
||||||
//! Returns period of full disconnect in seconds and period of averaging frequency
|
//! Returns period of full disconnect in seconds and period of averaging frequency
|
||||||
void setDisconnectTimeout(float s) { setProperty("disconnectTimeout", s); }
|
void setDisconnectTimeout(float s) DEPRECATEDM("use setDisconnectTimeout(PISystemTime)") {
|
||||||
|
setDisconnectTimeout(PISystemTime::fromSeconds(s));
|
||||||
|
}
|
||||||
|
|
||||||
//! Returns period of full disconnect and period of averaging frequency
|
//! Returns period of full disconnect and period of averaging frequency
|
||||||
void setDisconnectTimeout(PISystemTime tm) { setProperty("disconnectTimeout", tm.toSeconds()); }
|
void setDisconnectTimeout(PISystemTime tm) { setProperty("disconnectTimeout", tm); }
|
||||||
|
|
||||||
//! Returns connection quality
|
//! Returns connection quality
|
||||||
PIDiagnostics::Quality quality() const;
|
PIDiagnostics::Quality quality() const;
|
||||||
@@ -139,13 +141,13 @@ private:
|
|||||||
friend bool operator!=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s);
|
friend bool operator!=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s);
|
||||||
friend bool operator<(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s);
|
friend bool operator<(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s);
|
||||||
|
|
||||||
void tick(void *, int) override;
|
void tick(int) override;
|
||||||
Entry calcHistory(PIQueue<Entry> & hist, int & cnt);
|
Entry calcHistory(PIQueue<Entry> & hist, int & cnt);
|
||||||
void propertyChanged(const char *) override;
|
void propertyChanged(const char *) override;
|
||||||
void changeDisconnectTimeout(float disct);
|
void changeDisconnectTimeout(PISystemTime disct);
|
||||||
|
|
||||||
PIQueue<Entry> history_rec, history_send;
|
PIQueue<Entry> history_rec, history_send;
|
||||||
float disconn_ = 0.f;
|
PISystemTime disconn_;
|
||||||
State cur_state;
|
State cur_state;
|
||||||
mutable PIMutex mutex_state;
|
mutable PIMutex mutex_state;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ void PIPacketExtractor::construct() {
|
|||||||
func_footer = nullptr;
|
func_footer = nullptr;
|
||||||
func_payload = nullptr;
|
func_payload = nullptr;
|
||||||
setPayloadSize(0);
|
setPayloadSize(0);
|
||||||
setTimeout(100);
|
setTimeout(100_ms);
|
||||||
#ifdef MICRO_PIP
|
#ifdef MICRO_PIP
|
||||||
setThreadedReadBufferSize(512);
|
setThreadedReadBufferSize(512);
|
||||||
#else
|
#else
|
||||||
@@ -115,7 +115,7 @@ void PIPacketExtractor::propertyChanged(const char *) {
|
|||||||
dataSize = property("payloadSize").toInt();
|
dataSize = property("payloadSize").toInt();
|
||||||
src_header = property("header").toByteArray();
|
src_header = property("header").toByteArray();
|
||||||
src_footer = property("footer").toByteArray();
|
src_footer = property("footer").toByteArray();
|
||||||
time_ = property("timeout").toDouble();
|
time_ = property("timeout").toSystemTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public:
|
|||||||
Footer /** Detect packets with \a footer() and leading \a payloadSize() */,
|
Footer /** Detect packets with \a footer() and leading \a payloadSize() */,
|
||||||
HeaderAndFooter /** Detect packets with \a header() and \a footer() without \a payloadSize() */,
|
HeaderAndFooter /** Detect packets with \a header() and \a footer() without \a payloadSize() */,
|
||||||
Size /** Detect packets with \a packetSize() */,
|
Size /** Detect packets with \a packetSize() */,
|
||||||
Timeout /** Wait for first read, then read for \a timeout() milliseconds */
|
Timeout /** Wait for first read, then read for \a timeout() */
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Contructs extractor with child device "device_" and extract algorithm "mode"
|
//! Contructs extractor with child device "device_" and extract algorithm "mode"
|
||||||
@@ -87,8 +87,8 @@ public:
|
|||||||
//! Set footer data, used for PIPacketExtractor::Footer and PIPacketExtractor::HeaderAndFooter algorithms
|
//! Set footer data, used for PIPacketExtractor::Footer and PIPacketExtractor::HeaderAndFooter algorithms
|
||||||
void setFooter(const PIByteArray & data);
|
void setFooter(const PIByteArray & data);
|
||||||
|
|
||||||
//! Set timeout in milliseconds, used for PIPacketExtractor::Timeout algorithm
|
//! Set timeout, used for PIPacketExtractor::Timeout algorithm
|
||||||
void setTimeout(double msecs) { setProperty("timeout", msecs); }
|
void setTimeout(PISystemTime tm) { setProperty("timeout", tm); }
|
||||||
|
|
||||||
|
|
||||||
//! Returns current extract algorithm
|
//! Returns current extract algorithm
|
||||||
@@ -105,7 +105,7 @@ public:
|
|||||||
PIByteArray footer() const { return src_footer; }
|
PIByteArray footer() const { return src_footer; }
|
||||||
|
|
||||||
//! Returns current timeout in milliseconds, used for PIPacketExtractor::Timeout algorithm
|
//! Returns current timeout in milliseconds, used for PIPacketExtractor::Timeout algorithm
|
||||||
double timeout() const { return time_; }
|
PISystemTime timeout() const { return time_; }
|
||||||
|
|
||||||
//! Returns missed by validating functions bytes count
|
//! Returns missed by validating functions bytes count
|
||||||
ullong missedBytes() const { return missed; }
|
ullong missedBytes() const { return missed; }
|
||||||
@@ -165,7 +165,7 @@ private:
|
|||||||
PacketExtractorFooterFunc func_footer;
|
PacketExtractorFooterFunc func_footer;
|
||||||
SplitMode mode_;
|
SplitMode mode_;
|
||||||
int dataSize, packetSize_pending, footerInd;
|
int dataSize, packetSize_pending, footerInd;
|
||||||
double time_;
|
PISystemTime time_;
|
||||||
bool header_found;
|
bool header_found;
|
||||||
ullong missed;
|
ullong missed;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "pigeomodule.h"
|
#include "pigeomodule.h"
|
||||||
#include "piiodevicesmodule.h"
|
#include "piiodevicesmodule.h"
|
||||||
#include "piioutilsmodule.h"
|
#include "piioutilsmodule.h"
|
||||||
|
#include "piliterals.h"
|
||||||
#include "pimathmodule.h"
|
#include "pimathmodule.h"
|
||||||
#include "pistatemachinemodule.h"
|
#include "pistatemachinemodule.h"
|
||||||
#include "pisystemmodule.h"
|
#include "pisystemmodule.h"
|
||||||
|
|||||||
@@ -102,13 +102,13 @@ PITransitionTimeout::PITransitionTimeout(PIStateBase * source, PIStateBase * tar
|
|||||||
timer.setInterval(timeout);
|
timer.setInterval(timeout);
|
||||||
timer.setSlot([this] {
|
timer.setSlot([this] {
|
||||||
trigger();
|
trigger();
|
||||||
timer.stopLater();
|
timer.stop();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PITransitionTimeout::~PITransitionTimeout() {
|
PITransitionTimeout::~PITransitionTimeout() {
|
||||||
timer.stop();
|
timer.stopAndWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -118,5 +118,5 @@ void PITransitionTimeout::enabled() {
|
|||||||
|
|
||||||
|
|
||||||
void PITransitionTimeout::disabled() {
|
void PITransitionTimeout::disabled() {
|
||||||
timer.stopLater();
|
timer.stop();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,12 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "piliterals_time.h"
|
||||||
|
#include "pitime.h"
|
||||||
#ifndef MICRO_PIP
|
#ifndef MICRO_PIP
|
||||||
|
|
||||||
# include "piprocess.h"
|
|
||||||
|
|
||||||
# include "piincludes_p.h"
|
# include "piincludes_p.h"
|
||||||
|
# include "piprocess.h"
|
||||||
# ifndef WINDOWS
|
# ifndef WINDOWS
|
||||||
# include <csignal>
|
# include <csignal>
|
||||||
# include <sys/wait.h>
|
# include <sys/wait.h>
|
||||||
@@ -88,6 +89,7 @@ PIProcess::PIProcess(): PIThread() {
|
|||||||
|
|
||||||
|
|
||||||
PIProcess::~PIProcess() {
|
PIProcess::~PIProcess() {
|
||||||
|
PIThread::stopAndWait();
|
||||||
if (t_in) f_in.remove();
|
if (t_in) f_in.remove();
|
||||||
if (t_out) f_out.remove();
|
if (t_out) f_out.remove();
|
||||||
if (t_err) f_err.remove();
|
if (t_err) f_err.remove();
|
||||||
@@ -232,6 +234,11 @@ else {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIProcess::waitForFinish() {
|
||||||
|
return PIThread::waitForFinish(1_m);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIProcess::execIndependent(const PIString & program, const PIStringList & args_) {
|
void PIProcess::execIndependent(const PIString & program, const PIStringList & args_) {
|
||||||
PIProcess p;
|
PIProcess p;
|
||||||
p.args << program << args_;
|
p.args << program << args_;
|
||||||
|
|||||||
@@ -147,8 +147,8 @@ public:
|
|||||||
exec_();
|
exec_();
|
||||||
}
|
}
|
||||||
EVENT_HANDLER(void, terminate);
|
EVENT_HANDLER(void, terminate);
|
||||||
EVENT_HANDLER(bool, waitForFinish) { return waitForFinish(60000); }
|
EVENT_HANDLER(bool, waitForFinish);
|
||||||
EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs) { return PIThread::waitForFinish(timeout_msecs); }
|
EVENT_HANDLER1(bool, waitForFinish, PISystemTime, timeout) { return PIThread::waitForFinish(timeout); }
|
||||||
|
|
||||||
EVENT1(execStarted, PIString, program);
|
EVENT1(execStarted, PIString, program);
|
||||||
EVENT2(execFinished, PIString, program, int, exit_code);
|
EVENT2(execFinished, PIString, program, int, exit_code);
|
||||||
@@ -202,9 +202,9 @@ public:
|
|||||||
//! \~english Wait for attached execution finish maximum for 60 seconds
|
//! \~english Wait for attached execution finish maximum for 60 seconds
|
||||||
//! \~russian
|
//! \~russian
|
||||||
|
|
||||||
//! \fn bool waitForFinish(int timeout_msecs)
|
//! \fn bool waitForFinish(PISystemTime timeout)
|
||||||
//! \brief
|
//! \brief
|
||||||
//! \~english Wait for attached execution finish maximum for "timeout_msecs" milliseconds
|
//! \~english Wait for attached execution finish maximum for "timeout_"
|
||||||
//! \~russian
|
//! \~russian
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
|
|||||||
@@ -19,8 +19,10 @@
|
|||||||
|
|
||||||
#include "pisingleapplication.h"
|
#include "pisingleapplication.h"
|
||||||
|
|
||||||
#include "piliterals.h"
|
#include "piliterals_bytes.h"
|
||||||
|
#include "piliterals_time.h"
|
||||||
#include "pisharedmemory.h"
|
#include "pisharedmemory.h"
|
||||||
|
#include "pitime.h"
|
||||||
|
|
||||||
|
|
||||||
//! \class PISingleApplication pisingleapplication.h
|
//! \class PISingleApplication pisingleapplication.h
|
||||||
@@ -70,7 +72,7 @@ PISingleApplication::PISingleApplication(const PIString & app_name): PIThread()
|
|||||||
started = false;
|
started = false;
|
||||||
sacnt = 0;
|
sacnt = 0;
|
||||||
shm = new PISharedMemory("sa_" + app_name, SHM_SIZE);
|
shm = new PISharedMemory("sa_" + app_name, SHM_SIZE);
|
||||||
start(100);
|
start(10_Hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ PISystemMonitor::~PISystemMonitor() {
|
|||||||
|
|
||||||
|
|
||||||
#ifndef MICRO_PIP
|
#ifndef MICRO_PIP
|
||||||
bool PISystemMonitor::startOnProcess(int pID, int interval_ms) {
|
bool PISystemMonitor::startOnProcess(int pID, PISystemTime interval) {
|
||||||
stop();
|
stop();
|
||||||
pID_ = pID;
|
pID_ = pID;
|
||||||
Pool::instance()->add(this);
|
Pool::instance()->add(this);
|
||||||
@@ -118,17 +118,17 @@ bool PISystemMonitor::startOnProcess(int pID, int interval_ms) {
|
|||||||
}
|
}
|
||||||
PRIVATE->tm.reset();
|
PRIVATE->tm.reset();
|
||||||
# endif
|
# endif
|
||||||
return start(interval_ms);
|
return start(interval);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
bool PISystemMonitor::startOnSelf(int interval_ms) {
|
bool PISystemMonitor::startOnSelf(PISystemTime interval) {
|
||||||
#ifndef MICRO_PIP
|
#ifndef MICRO_PIP
|
||||||
bool ret = startOnProcess(PIProcess::currentPID(), interval_ms);
|
bool ret = startOnProcess(PIProcess::currentPID(), interval);
|
||||||
cycle = -1;
|
cycle = -1;
|
||||||
#else
|
#else
|
||||||
bool ret = start(interval_ms);
|
bool ret = start(interval);
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,8 @@ void PISystemMonitor::run() {
|
|||||||
if (t->isPIObject()) gatherThread(t->tid());
|
if (t->isPIObject()) gatherThread(t->tid());
|
||||||
#else
|
#else
|
||||||
# ifndef WINDOWS
|
# ifndef WINDOWS
|
||||||
tbid[pID_] = "main";
|
double delay_ms = delay_.toMilliseconds();
|
||||||
|
tbid[pID_] = "main";
|
||||||
# ifdef MAC_OS
|
# ifdef MAC_OS
|
||||||
rusage_info_current ru;
|
rusage_info_current ru;
|
||||||
proc_pid_rusage(pID_, RUSAGE_INFO_CURRENT, (rusage_info_t *)&ru);
|
proc_pid_rusage(pID_, RUSAGE_INFO_CURRENT, (rusage_info_t *)&ru);
|
||||||
@@ -203,10 +204,10 @@ void PISystemMonitor::run() {
|
|||||||
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
|
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
|
||||||
PRIVATE->cpu_u_cur = uint64toST(ru.ri_user_time);
|
PRIVATE->cpu_u_cur = uint64toST(ru.ri_user_time);
|
||||||
PRIVATE->cpu_s_cur = uint64toST(ru.ri_system_time);
|
PRIVATE->cpu_s_cur = uint64toST(ru.ri_system_time);
|
||||||
tstat.cpu_load_system = 100.f * (PRIVATE->cpu_s_cur - PRIVATE->cpu_s_prev).toMilliseconds() / delay_;
|
tstat.cpu_load_system = 100.f * (PRIVATE->cpu_s_cur - PRIVATE->cpu_s_prev).toMilliseconds() / delay_ms;
|
||||||
tstat.cpu_load_user = 100.f * (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_;
|
tstat.cpu_load_user = 100.f * (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_ms;
|
||||||
cycle = 0;
|
cycle = 0;
|
||||||
// piCout << (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_;
|
// piCout << (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_ms;
|
||||||
# else
|
# else
|
||||||
PRIVATE->file.seekToBegin();
|
PRIVATE->file.seekToBegin();
|
||||||
PIString str = PIString::fromAscii(PRIVATE->file.readAll(true));
|
PIString str = PIString::fromAscii(PRIVATE->file.readAll(true));
|
||||||
@@ -236,8 +237,8 @@ void PISystemMonitor::run() {
|
|||||||
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
|
PRIVATE->cpu_s_prev = PRIVATE->cpu_s_cur;
|
||||||
PRIVATE->cpu_u_cur = sl[12].toLLong();
|
PRIVATE->cpu_u_cur = sl[12].toLLong();
|
||||||
PRIVATE->cpu_s_cur = sl[13].toLLong();
|
PRIVATE->cpu_s_cur = sl[13].toLLong();
|
||||||
tstat.cpu_load_system = (PRIVATE->cpu_s_cur - PRIVATE->cpu_s_prev) / (delay_ / 1000.);
|
tstat.cpu_load_system = (PRIVATE->cpu_s_cur - PRIVATE->cpu_s_prev) / (delay_ms / 1000.);
|
||||||
tstat.cpu_load_user = (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev) / (delay_ / 1000.);
|
tstat.cpu_load_user = (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev) / (delay_ms / 1000.);
|
||||||
tstat.cpu_load_system /= cpu_count;
|
tstat.cpu_load_system /= cpu_count;
|
||||||
tstat.cpu_load_user /= cpu_count;
|
tstat.cpu_load_user /= cpu_count;
|
||||||
cycle = 0;
|
cycle = 0;
|
||||||
@@ -394,8 +395,8 @@ void PISystemMonitor::gatherThread(llong id) {
|
|||||||
|
|
||||||
|
|
||||||
float PISystemMonitor::calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old) {
|
float PISystemMonitor::calcThreadUsage(PISystemTime & t_new, PISystemTime & t_old) {
|
||||||
if (delay_ <= 0) return -1.;
|
if (delay_.isNull()) return -1.;
|
||||||
return piClampf(100. * ((t_new - t_old).toMilliseconds() / delay_), 0.f, 100.f);
|
return piClampf(100. * ((t_new - t_old).toMilliseconds() / delay_.toMilliseconds()), 0.f, 100.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -203,12 +203,12 @@ public:
|
|||||||
|
|
||||||
//! \~english Starts monitoring of process with PID "pID" and update interval "interval_ms" milliseconds
|
//! \~english Starts monitoring of process with PID "pID" and update interval "interval_ms" milliseconds
|
||||||
//! \~russian Начинает мониторинг процесса с PID "pID" и интервалом обновления "interval_ms" миллисекунд
|
//! \~russian Начинает мониторинг процесса с PID "pID" и интервалом обновления "interval_ms" миллисекунд
|
||||||
bool startOnProcess(int pID, int interval_ms = 1000);
|
bool startOnProcess(int pID, PISystemTime interval = PISystemTime::fromSeconds(1.));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//! \~english Starts monitoring of application process with update interval "interval_ms" milliseconds
|
//! \~english Starts monitoring of application process with update interval "interval_ms" milliseconds
|
||||||
//! \~russian Начинает мониторинг процесса приложения с интервалом обновления "interval_ms" миллисекунд
|
//! \~russian Начинает мониторинг процесса приложения с интервалом обновления "interval_ms" миллисекунд
|
||||||
bool startOnSelf(int interval_ms = 1000);
|
bool startOnSelf(PISystemTime interval = PISystemTime::fromSeconds(1.));
|
||||||
|
|
||||||
//! \~english Stop monitoring
|
//! \~english Stop monitoring
|
||||||
//! \~russian Останавливает мониторинг
|
//! \~russian Останавливает мониторинг
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
#define PIBLOCKINGQUEUE_H
|
#define PIBLOCKINGQUEUE_H
|
||||||
|
|
||||||
#include "piconditionvar.h"
|
#include "piconditionvar.h"
|
||||||
#include "pideque.h"
|
#include "piqueue.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A Queue that supports operations that wait for the queue to become non-empty when retrieving an element, and
|
* \brief A Queue that supports operations that wait for the queue to become non-empty when retrieving an element, and
|
||||||
@@ -96,16 +96,16 @@ public:
|
|||||||
* exceeding the queue's capacity, returning true upon success and false if this queue is full.
|
* exceeding the queue's capacity, returning true upon success and false if this queue is full.
|
||||||
*
|
*
|
||||||
* @param v the element to add
|
* @param v the element to add
|
||||||
* @param timeoutMs the timeout waiting for inserting if que is full, if timeout = 0, then returns immediately
|
* @param timeout the timeout waiting for inserting if que is full, if timeout is null, then returns immediately
|
||||||
* @return true if the element was added to this queue, else false
|
* @return true if the element was added to this queue, else false
|
||||||
*/
|
*/
|
||||||
bool offer(const T & v, int timeoutMs = 0) {
|
bool offer(const T & v, PISystemTime timeout = {}) {
|
||||||
bool isOk;
|
bool isOk;
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
if (timeoutMs == 0)
|
if (timeout.isNull())
|
||||||
isOk = PIDeque<T>::size() < max_size;
|
isOk = PIDeque<T>::size() < max_size;
|
||||||
else
|
else
|
||||||
isOk = cond_var_rem->waitFor(mutex, timeoutMs, [&]() { return PIDeque<T>::size() < max_size; });
|
isOk = cond_var_rem->waitFor(mutex, timeout, [&]() { return PIDeque<T>::size() < max_size; });
|
||||||
if (isOk) PIDeque<T>::push_back(v);
|
if (isOk) PIDeque<T>::push_back(v);
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
if (isOk) cond_var_add->notifyOne();
|
if (isOk) cond_var_add->notifyOne();
|
||||||
@@ -133,20 +133,20 @@ public:
|
|||||||
* \brief Retrieves and removes the head of this queue, waiting up to the specified wait time if necessary for an
|
* \brief Retrieves and removes the head of this queue, waiting up to the specified wait time if necessary for an
|
||||||
* element to become available.
|
* element to become available.
|
||||||
*
|
*
|
||||||
* @param timeoutMs how long to wait before giving up, in milliseconds
|
* @param timeout how long to wait before giving up
|
||||||
* @param defaultVal value, which returns if the specified waiting time elapses before an element is available
|
* @param defaultVal value, which returns if the specified waiting time elapses before an element is available
|
||||||
* @param isOk flag, which indicates result of method execution. It will be set to false if timeout, or true if
|
* @param isOk flag, which indicates result of method execution. It will be set to false if timeout, or true if
|
||||||
* return value is retrieved value
|
* return value is retrieved value
|
||||||
* @return the head of this queue, or defaultVal if the specified waiting time elapses before an element is available
|
* @return the head of this queue, or defaultVal if the specified waiting time elapses before an element is available
|
||||||
*/
|
*/
|
||||||
T poll(int timeoutMs = 0, const T & defaultVal = T(), bool * isOk = nullptr) {
|
T poll(PISystemTime timeout = {}, const T & defaultVal = T(), bool * isOk = nullptr) {
|
||||||
T t = defaultVal;
|
T t = defaultVal;
|
||||||
bool isNotEmpty;
|
bool isNotEmpty;
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
if (timeoutMs == 0)
|
if (timeout.isNull())
|
||||||
isNotEmpty = !PIDeque<T>::isEmpty();
|
isNotEmpty = !PIDeque<T>::isEmpty();
|
||||||
else
|
else
|
||||||
isNotEmpty = cond_var_add->waitFor(mutex, timeoutMs, [&]() { return !PIDeque<T>::isEmpty(); });
|
isNotEmpty = cond_var_add->waitFor(mutex, timeout, [&]() { return !PIDeque<T>::isEmpty(); });
|
||||||
if (isNotEmpty) t = PIDeque<T>::take_front();
|
if (isNotEmpty) t = PIDeque<T>::take_front();
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
if (isNotEmpty) cond_var_rem->notifyOne();
|
if (isNotEmpty) cond_var_rem->notifyOne();
|
||||||
|
|||||||
@@ -25,8 +25,6 @@
|
|||||||
|
|
||||||
#include "piconditionvar.h"
|
#include "piconditionvar.h"
|
||||||
#include "piincludes_p.h"
|
#include "piincludes_p.h"
|
||||||
#include "pithread.h"
|
|
||||||
#include "pitime.h"
|
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
# include <synchapi.h>
|
# include <synchapi.h>
|
||||||
# include <winbase.h>
|
# include <winbase.h>
|
||||||
@@ -105,19 +103,18 @@ void PIConditionVariable::wait(PIMutex & lk, const std::function<bool()> & condi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIConditionVariable::waitFor(PIMutex & lk, int timeoutMs) {
|
bool PIConditionVariable::waitFor(PIMutex & lk, PISystemTime timeout) {
|
||||||
bool isNotTimeout;
|
bool isNotTimeout;
|
||||||
#if defined(WINDOWS)
|
#if defined(WINDOWS)
|
||||||
isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0;
|
isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeout.toMilliseconds()) != 0;
|
||||||
#elif defined(FREERTOS)
|
#elif defined(FREERTOS)
|
||||||
xEventGroupClearBits(PRIVATE->nativeHandle, 1);
|
xEventGroupClearBits(PRIVATE->nativeHandle, 1);
|
||||||
EventBits_t uxBits;
|
EventBits_t uxBits;
|
||||||
uxBits = xEventGroupWaitBits(PRIVATE->nativeHandle, 1, pdTRUE, pdTRUE, timeoutMs / portTICK_PERIOD_MS);
|
uxBits = xEventGroupWaitBits(PRIVATE->nativeHandle, 1, pdTRUE, pdTRUE, timeout.toMilliseconds() / portTICK_PERIOD_MS);
|
||||||
isNotTimeout = (uxBits & 1) != 0;
|
isNotTimeout = (uxBits & 1) != 0;
|
||||||
#else
|
#else
|
||||||
|
PISystemTime st = PISystemTime::current(true) + timeout;
|
||||||
timespec expire_ts;
|
timespec expire_ts;
|
||||||
PISystemTime st = PISystemTime::current(true);
|
|
||||||
st.addMilliseconds(timeoutMs);
|
|
||||||
st.toTimespec(&expire_ts);
|
st.toTimespec(&expire_ts);
|
||||||
isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t *)lk.handle(), &expire_ts) == 0;
|
isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t *)lk.handle(), &expire_ts) == 0;
|
||||||
#endif
|
#endif
|
||||||
@@ -125,14 +122,13 @@ bool PIConditionVariable::waitFor(PIMutex & lk, int timeoutMs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIConditionVariable::waitFor(PIMutex & lk, int timeoutMs, const std::function<bool()> & condition) {
|
bool PIConditionVariable::waitFor(PIMutex & lk, PISystemTime timeout, const std::function<bool()> & condition) {
|
||||||
bool isCondition;
|
bool isCondition;
|
||||||
#if defined(WINDOWS) || defined(FREERTOS)
|
#if defined(WINDOWS) || defined(FREERTOS)
|
||||||
PITimeMeasurer measurer;
|
PITimeMeasurer measurer;
|
||||||
#else
|
#else
|
||||||
|
PISystemTime st = PISystemTime::current(true) + timeout;
|
||||||
timespec expire_ts;
|
timespec expire_ts;
|
||||||
PISystemTime st = PISystemTime::current(true);
|
|
||||||
st.addMilliseconds(timeoutMs);
|
|
||||||
st.toTimespec(&expire_ts);
|
st.toTimespec(&expire_ts);
|
||||||
#endif
|
#endif
|
||||||
#ifdef FREERTOS
|
#ifdef FREERTOS
|
||||||
@@ -143,12 +139,16 @@ bool PIConditionVariable::waitFor(PIMutex & lk, int timeoutMs, const std::functi
|
|||||||
if (isCondition) break;
|
if (isCondition) break;
|
||||||
bool isTimeout;
|
bool isTimeout;
|
||||||
#if defined(WINDOWS)
|
#if defined(WINDOWS)
|
||||||
isTimeout =
|
isTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle,
|
||||||
SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs - (int)measurer.elapsed_m()) == 0;
|
(PCRITICAL_SECTION)lk.handle(),
|
||||||
|
timeout.toMilliseconds() - (int)measurer.elapsed_m()) == 0;
|
||||||
#elif defined(FREERTOS)
|
#elif defined(FREERTOS)
|
||||||
EventBits_t uxBits;
|
EventBits_t uxBits;
|
||||||
uxBits =
|
uxBits = xEventGroupWaitBits(PRIVATE->nativeHandle,
|
||||||
xEventGroupWaitBits(PRIVATE->nativeHandle, 1, pdTRUE, pdTRUE, (timeoutMs - (int)measurer.elapsed_m()) / portTICK_PERIOD_MS);
|
1,
|
||||||
|
pdTRUE,
|
||||||
|
pdTRUE,
|
||||||
|
(timeout.toMilliseconds() - (int)measurer.elapsed_m()) / portTICK_PERIOD_MS);
|
||||||
isTimeout = (uxBits & 1) == 0;
|
isTimeout = (uxBits & 1) == 0;
|
||||||
#else
|
#else
|
||||||
isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t *)lk.handle(), &expire_ts) != 0;
|
isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t *)lk.handle(), &expire_ts) != 0;
|
||||||
|
|||||||
@@ -26,7 +26,8 @@
|
|||||||
#ifndef PICONDITIONVAR_H
|
#ifndef PICONDITIONVAR_H
|
||||||
#define PICONDITIONVAR_H
|
#define PICONDITIONVAR_H
|
||||||
|
|
||||||
#include "pithread.h"
|
#include "pimutex.h"
|
||||||
|
#include "pisystemtime.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,18 +88,18 @@ public:
|
|||||||
/**
|
/**
|
||||||
* \brief see waitFor(PIMutex &, int, const std::function<bool()>&)
|
* \brief see waitFor(PIMutex &, int, const std::function<bool()>&)
|
||||||
*/
|
*/
|
||||||
virtual bool waitFor(PIMutex & lk, int timeoutMs);
|
virtual bool waitFor(PIMutex & lk, PISystemTime timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Wait for timeout or until notified
|
* \brief Wait for timeout or until notified
|
||||||
*
|
*
|
||||||
* The execution of the current thread (which shall have locked with lk method PIMutex::lock()) is blocked
|
* The execution of the current thread (which shall have locked with lk method PIMutex::lock()) is blocked
|
||||||
* during timeoutMs, or until notified (if the latter happens first).
|
* during timeout, or until notified (if the latter happens first).
|
||||||
*
|
*
|
||||||
* At the moment of blocking the thread, the function automatically calls lk.lock() (PIMutex::lock()), allowing
|
* At the moment of blocking the thread, the function automatically calls lk.lock() (PIMutex::lock()), allowing
|
||||||
* other locked threads to continue.
|
* other locked threads to continue.
|
||||||
*
|
*
|
||||||
* Once notified or once timeoutMs has passed, the function unblocks and calls lk.unlock() (PIMutex::unlock()),
|
* Once notified or once timeout has passed, the function unblocks and calls lk.unlock() (PIMutex::unlock()),
|
||||||
* leaving lk in the same state as when the function was called. Then the function returns (notice that this last
|
* leaving lk in the same state as when the function was called. Then the function returns (notice that this last
|
||||||
* mutex locking may block again the thread before returning).
|
* mutex locking may block again the thread before returning).
|
||||||
*
|
*
|
||||||
@@ -114,7 +115,7 @@ public:
|
|||||||
* as a bool. This is called repeatedly until it evaluates to true.
|
* as a bool. This is called repeatedly until it evaluates to true.
|
||||||
* @return false if timeout reached or true if wakeup condition is true
|
* @return false if timeout reached or true if wakeup condition is true
|
||||||
*/
|
*/
|
||||||
virtual bool waitFor(PIMutex & lk, int timeoutMs, const std::function<bool()> & condition);
|
virtual bool waitFor(PIMutex & lk, PISystemTime timeout, const std::function<bool()> & condition);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PRIVATE_DECLARATION(PIP_EXPORT)
|
PRIVATE_DECLARATION(PIP_EXPORT)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "pidiagnostics.h"
|
#include "pidiagnostics.h"
|
||||||
#include "pithread.h"
|
#include "pithread.h"
|
||||||
|
#include "pitime.h"
|
||||||
|
|
||||||
|
|
||||||
template<typename T = PIByteArray>
|
template<typename T = PIByteArray>
|
||||||
|
|||||||
@@ -535,33 +535,33 @@ PRIVATE_DEFINITION_START(PIThread)
|
|||||||
PRIVATE_DEFINITION_END(PIThread)
|
PRIVATE_DEFINITION_END(PIThread)
|
||||||
|
|
||||||
|
|
||||||
PIThread::PIThread(void * data, ThreadFunc func, bool startNow, int loop_delay): PIObject() {
|
PIThread::PIThread(void * data, ThreadFunc func, bool startNow, PISystemTime loop_delay): PIObject() {
|
||||||
PIINTROSPECTION_THREAD_NEW(this);
|
PIINTROSPECTION_THREAD_NEW(this);
|
||||||
data_ = data;
|
data_ = data;
|
||||||
ret_func = func;
|
ret_func = func;
|
||||||
terminating = running_ = lockRun = false;
|
terminating = running_ = lockRun = false;
|
||||||
priority_ = piNormal;
|
priority_ = piNormal;
|
||||||
delay_ = loop_delay;
|
delay_ = loop_delay;
|
||||||
if (startNow) start(loop_delay);
|
if (startNow) start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIThread::PIThread(std::function<void()> func, bool startNow, int loop_delay) {
|
PIThread::PIThread(std::function<void()> func, bool startNow, PISystemTime loop_delay) {
|
||||||
PIINTROSPECTION_THREAD_NEW(this);
|
PIINTROSPECTION_THREAD_NEW(this);
|
||||||
ret_func = [func](void *) { func(); };
|
ret_func = [func](void *) { func(); };
|
||||||
terminating = running_ = lockRun = false;
|
terminating = running_ = lockRun = false;
|
||||||
priority_ = piNormal;
|
priority_ = piNormal;
|
||||||
delay_ = loop_delay;
|
delay_ = loop_delay;
|
||||||
if (startNow) start(loop_delay);
|
if (startNow) start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIThread::PIThread(bool startNow, int loop_delay): PIObject() {
|
PIThread::PIThread(bool startNow, PISystemTime loop_delay): PIObject() {
|
||||||
PIINTROSPECTION_THREAD_NEW(this);
|
PIINTROSPECTION_THREAD_NEW(this);
|
||||||
terminating = running_ = lockRun = false;
|
terminating = running_ = lockRun = false;
|
||||||
priority_ = piNormal;
|
priority_ = piNormal;
|
||||||
delay_ = loop_delay;
|
delay_ = loop_delay;
|
||||||
if (startNow) start(loop_delay);
|
if (startNow) start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -573,7 +573,7 @@ PIThread::~PIThread() {
|
|||||||
// PICout(PICoutManipulators::DefaultControls) << "~PIThread" << PRIVATE->thread;
|
// PICout(PICoutManipulators::DefaultControls) << "~PIThread" << PRIVATE->thread;
|
||||||
// PICout(PICoutManipulators::DefaultControls) << pthread_join(PRIVATE->thread, 0);
|
// PICout(PICoutManipulators::DefaultControls) << pthread_join(PRIVATE->thread, 0);
|
||||||
PICout(PICoutManipulators::DefaultControls) << "FreeRTOS can't terminate pthreads! waiting for stop";
|
PICout(PICoutManipulators::DefaultControls) << "FreeRTOS can't terminate pthreads! waiting for stop";
|
||||||
stop(true);
|
stopAndWait();
|
||||||
// PICout(PICoutManipulators::DefaultControls) << "stopped!";
|
// PICout(PICoutManipulators::DefaultControls) << "stopped!";
|
||||||
#else
|
#else
|
||||||
# ifndef WINDOWS
|
# ifndef WINDOWS
|
||||||
@@ -591,15 +591,47 @@ PIThread::~PIThread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIThread::start(ThreadFunc func, int loop_delay) {
|
bool PIThread::start() {
|
||||||
ret_func = func;
|
if (running_) return false;
|
||||||
return start(loop_delay);
|
return _startThread((void *)thread_function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIThread::start(std::function<void()> func, int loop_delay) {
|
bool PIThread::start(PISystemTime loop_delay) {
|
||||||
|
delay_ = loop_delay;
|
||||||
|
return start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIThread::start(ThreadFunc func) {
|
||||||
|
ret_func = func;
|
||||||
|
return start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIThread::start(ThreadFunc func, PISystemTime loop_delay) {
|
||||||
|
ret_func = func;
|
||||||
|
delay_ = loop_delay;
|
||||||
|
return start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIThread::start(std::function<void()> func) {
|
||||||
ret_func = [func](void *) { func(); };
|
ret_func = [func](void *) { func(); };
|
||||||
return start(loop_delay);
|
return start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIThread::start(std::function<void()> func, PISystemTime loop_delay) {
|
||||||
|
ret_func = [func](void *) { func(); };
|
||||||
|
delay_ = loop_delay;
|
||||||
|
return start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIThread::startOnce() {
|
||||||
|
if (running_) return false;
|
||||||
|
return _startThread((void *)thread_function_once);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -609,9 +641,15 @@ bool PIThread::startOnce(ThreadFunc func) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIThread::stopAndWait(int timeout_ms) {
|
bool PIThread::startOnce(std::function<void()> func) {
|
||||||
|
ret_func = [func](void *) { func(); };
|
||||||
|
return startOnce();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIThread::stopAndWait(PISystemTime timeout) {
|
||||||
stop();
|
stop();
|
||||||
waitForFinish(timeout_ms);
|
waitForFinish(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -621,19 +659,6 @@ void PIThread::stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIThread::start(int loop_delay) {
|
|
||||||
if (running_) return false;
|
|
||||||
delay_ = loop_delay;
|
|
||||||
return _startThread((void *)thread_function);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PIThread::startOnce() {
|
|
||||||
if (running_) return false;
|
|
||||||
return _startThread((void *)thread_function_once);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIThread::terminate() {
|
void PIThread::terminate() {
|
||||||
piCoutObj << "Warning, terminate!";
|
piCoutObj << "Warning, terminate!";
|
||||||
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "terminate ..." << running_;
|
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "terminate ..." << running_;
|
||||||
@@ -766,7 +791,7 @@ void PIThread::setPriority(PIThread::Priority prior) {
|
|||||||
#else
|
#else
|
||||||
# ifndef WINDOWS
|
# ifndef WINDOWS
|
||||||
// PICout(PICoutManipulators::DefaultControls) << "setPriority" << PRIVATE->thread;
|
// PICout(PICoutManipulators::DefaultControls) << "setPriority" << PRIVATE->thread;
|
||||||
policy_ = 0;
|
int policy_ = 0;
|
||||||
memset(&(PRIVATE->sparam), 0, sizeof(PRIVATE->sparam));
|
memset(&(PRIVATE->sparam), 0, sizeof(PRIVATE->sparam));
|
||||||
pthread_getschedparam(PRIVATE->thread, &policy_, &(PRIVATE->sparam));
|
pthread_getschedparam(PRIVATE->thread, &policy_, &(PRIVATE->sparam));
|
||||||
PRIVATE->sparam.
|
PRIVATE->sparam.
|
||||||
@@ -785,16 +810,6 @@ void PIThread::setPriority(PIThread::Priority prior) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIThread::waitForStart(PISystemTime timeout) {
|
|
||||||
return waitForStart(timeout.toMilliseconds());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PIThread::waitForFinish(PISystemTime timeout) {
|
|
||||||
return waitForFinish(timeout.toMilliseconds());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
bool isExists(HANDLE hThread) {
|
bool isExists(HANDLE hThread) {
|
||||||
// errorClear();
|
// errorClear();
|
||||||
@@ -808,11 +823,12 @@ bool isExists(HANDLE hThread) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool PIThread::waitForFinish(int timeout_msecs) {
|
|
||||||
|
bool PIThread::waitForFinish(PISystemTime timeout) {
|
||||||
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "PIThread::waitForFinish" << running_ << terminating <<
|
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "PIThread::waitForFinish" << running_ << terminating <<
|
||||||
// timeout_msecs;
|
// timeout_msecs;
|
||||||
if (!running_) return true;
|
if (!running_) return true;
|
||||||
if (timeout_msecs < 0) {
|
if (timeout.isNull()) {
|
||||||
while (running_) {
|
while (running_) {
|
||||||
piMinSleep();
|
piMinSleep();
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
@@ -825,7 +841,7 @@ bool PIThread::waitForFinish(int timeout_msecs) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
tmf_.reset();
|
tmf_.reset();
|
||||||
while (running_ && tmf_.elapsed_m() < timeout_msecs) {
|
while (running_ && tmf_.elapsed() < timeout) {
|
||||||
piMinSleep();
|
piMinSleep();
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
if (!isExists(PRIVATE->thread)) {
|
if (!isExists(PRIVATE->thread)) {
|
||||||
@@ -834,21 +850,21 @@ bool PIThread::waitForFinish(int timeout_msecs) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return tmf_.elapsed_m() < timeout_msecs;
|
return tmf_.elapsed() < timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIThread::waitForStart(int timeout_msecs) {
|
bool PIThread::waitForStart(PISystemTime timeout) {
|
||||||
if (running_) return true;
|
if (running_) return true;
|
||||||
if (timeout_msecs < 0) {
|
if (timeout.isNull()) {
|
||||||
while (!running_)
|
while (!running_)
|
||||||
piMinSleep();
|
piMinSleep();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
tms_.reset();
|
tms_.reset();
|
||||||
while (!running_ && tms_.elapsed_m() < timeout_msecs)
|
while (!running_ && tms_.elapsed() < timeout)
|
||||||
piMinSleep();
|
piMinSleep();
|
||||||
return tms_.elapsed_m() < timeout_msecs;
|
return tms_.elapsed() < timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -940,11 +956,11 @@ void PIThread::__thread_func__() {
|
|||||||
_runThread();
|
_runThread();
|
||||||
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "wait" << "...";
|
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "wait" << "...";
|
||||||
PIINTROSPECTION_THREAD_WAIT(this);
|
PIINTROSPECTION_THREAD_WAIT(this);
|
||||||
if (delay_ > 0) {
|
if (delay_.isNotNull()) {
|
||||||
tmr_.reset();
|
tmr_.reset();
|
||||||
double sl(0.);
|
double sl(0.);
|
||||||
while (1) {
|
while (1) {
|
||||||
sl = piMind(delay_ - tmr_.elapsed_m(), PIP_MIN_MSLEEP);
|
sl = piMind(delay_.toMilliseconds() - tmr_.elapsed_m(), PIP_MIN_MSLEEP);
|
||||||
if (terminating) break;
|
if (terminating) break;
|
||||||
if (sl <= 0.) break;
|
if (sl <= 0.) break;
|
||||||
piMSleep(sl);
|
piMSleep(sl);
|
||||||
|
|||||||
@@ -79,15 +79,15 @@ public:
|
|||||||
|
|
||||||
//! \~english Contructs thread with custom data "data", external function "func" and main loop delay "loop_delay"
|
//! \~english Contructs thread with custom data "data", external function "func" and main loop delay "loop_delay"
|
||||||
//! \~russian Создает поток с данными "data", функцией "func" и задержкой цикла "loop_delay"
|
//! \~russian Создает поток с данными "data", функцией "func" и задержкой цикла "loop_delay"
|
||||||
PIThread(void * data, ThreadFunc func, bool startNow = false, int loop_delay = -1);
|
PIThread(void * data, ThreadFunc func, bool startNow = false, PISystemTime loop_delay = {});
|
||||||
|
|
||||||
//! \~english Contructs thread with external function "func" and main loop delay "loop_delay"
|
//! \~english Contructs thread with external function "func" and main loop delay "loop_delay"
|
||||||
//! \~russian Создает поток с функцией "func" и задержкой цикла "loop_delay"
|
//! \~russian Создает поток с функцией "func" и задержкой цикла "loop_delay"
|
||||||
PIThread(std::function<void()> func, bool startNow = false, int loop_delay = -1);
|
PIThread(std::function<void()> func, bool startNow = false, PISystemTime loop_delay = {});
|
||||||
|
|
||||||
//! \~english Contructs thread with main loop delay "loop_delay"
|
//! \~english Contructs thread with main loop delay "loop_delay"
|
||||||
//! \~russian Создает поток с задержкой цикла "loop_delay"
|
//! \~russian Создает поток с задержкой цикла "loop_delay"
|
||||||
PIThread(bool startNow = false, int loop_delay = -1);
|
PIThread(bool startNow = false, PISystemTime loop_delay = {});
|
||||||
|
|
||||||
virtual ~PIThread();
|
virtual ~PIThread();
|
||||||
|
|
||||||
@@ -103,27 +103,55 @@ public:
|
|||||||
piHighest /** \~english Highest \~russian Высший */
|
piHighest /** \~english Highest \~russian Высший */
|
||||||
};
|
};
|
||||||
|
|
||||||
EVENT_HANDLER0(bool, start) { return start(-1); }
|
|
||||||
EVENT_HANDLER1(bool, start, int, loop_delay);
|
//! \~english Start thread
|
||||||
bool start(PISystemTime loop_delay) { return start(loop_delay.toMilliseconds()); }
|
//! \~russian Запускает поток
|
||||||
bool start(ThreadFunc func) { return start(func, -1); }
|
bool start();
|
||||||
bool start(ThreadFunc func, int loop_delay);
|
|
||||||
bool start(ThreadFunc func, PISystemTime loop_delay) { return start(func, loop_delay.toMilliseconds()); }
|
//! \~english Start thread
|
||||||
bool start(std::function<void()> func) { return start(func, -1); }
|
//! \~russian Запускает поток
|
||||||
bool start(std::function<void()> func, int loop_delay);
|
bool start(PISystemTime loop_delay);
|
||||||
bool start(std::function<void()> func, PISystemTime loop_delay) { return start(func, loop_delay.toMilliseconds()); }
|
|
||||||
EVENT_HANDLER0(bool, startOnce);
|
//! \~english Start thread
|
||||||
EVENT_HANDLER1(bool, startOnce, ThreadFunc, func);
|
//! \~russian Запускает поток
|
||||||
|
bool start(ThreadFunc func);
|
||||||
|
|
||||||
|
//! \~english Start thread
|
||||||
|
//! \~russian Запускает поток
|
||||||
|
bool start(ThreadFunc func, PISystemTime loop_delay);
|
||||||
|
|
||||||
|
//! \~english Start thread
|
||||||
|
//! \~russian Запускает поток
|
||||||
|
bool start(std::function<void()> func);
|
||||||
|
|
||||||
|
//! \~english Start thread
|
||||||
|
//! \~russian Запускает поток
|
||||||
|
bool start(std::function<void()> func, PISystemTime loop_delay);
|
||||||
|
|
||||||
|
//! \~english Start thread without internal loop
|
||||||
|
//! \~russian Запускает поток без внутреннего цикла
|
||||||
|
bool startOnce();
|
||||||
|
|
||||||
|
//! \~english Start thread without internal loop
|
||||||
|
//! \~russian Запускает поток без внутреннего цикла
|
||||||
|
bool startOnce(ThreadFunc func);
|
||||||
|
|
||||||
|
//! \~english Start thread without internal loop
|
||||||
|
//! \~russian Запускает поток без внутреннего цикла
|
||||||
|
bool startOnce(std::function<void()> func);
|
||||||
|
|
||||||
EVENT_HANDLER0(void, stop);
|
EVENT_HANDLER0(void, stop);
|
||||||
EVENT_HANDLER0(void, terminate);
|
EVENT_HANDLER0(void, terminate);
|
||||||
|
|
||||||
//! \~english Stop thread and wait for finish.
|
//! \~english Stop thread and wait for finish.
|
||||||
//! \~russian Останавливает поток и ожидает завершения.
|
//! \~russian Останавливает поток и ожидает завершения.
|
||||||
void stopAndWait(int timeout_ms = -1);
|
void stopAndWait(int timeout_ms) DEPRECATEDM("use waitForStart(PISystemTime)") {
|
||||||
|
stopAndWait(PISystemTime::fromMilliseconds(timeout_ms));
|
||||||
|
}
|
||||||
|
|
||||||
//! \~english Stop thread and wait for finish.
|
//! \~english Stop thread and wait for finish.
|
||||||
//! \~russian Останавливает поток и ожидает завершения.
|
//! \~russian Останавливает поток и ожидает завершения.
|
||||||
void stopAndWait(PISystemTime timeout) { stopAndWait(timeout.toMilliseconds()); }
|
void stopAndWait(PISystemTime timeout = {});
|
||||||
|
|
||||||
//! \~english Set common data passed to external function
|
//! \~english Set common data passed to external function
|
||||||
//! \~russian Устанавливает данные, передаваемые в функцию потока
|
//! \~russian Устанавливает данные, передаваемые в функцию потока
|
||||||
@@ -159,12 +187,19 @@ public:
|
|||||||
//! \~russian Возвращает останавливается ли поток
|
//! \~russian Возвращает останавливается ли поток
|
||||||
bool isStopping() const { return running_ && terminating; }
|
bool isStopping() const { return running_ && terminating; }
|
||||||
|
|
||||||
EVENT_HANDLER0(bool, waitForStart) { return waitForStart(-1); }
|
//! \~english Wait for thread start
|
||||||
EVENT_HANDLER1(bool, waitForStart, int, timeout_msecs);
|
//! \~russian Ожидает старта потока
|
||||||
bool waitForStart(PISystemTime timeout);
|
bool waitForStart(PISystemTime timeout = {});
|
||||||
EVENT_HANDLER0(bool, waitForFinish) { return waitForFinish(-1); }
|
bool waitForStart(int timeout_msecs) DEPRECATEDM("use waitForStart(PISystemTime)") {
|
||||||
EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs);
|
return waitForStart(PISystemTime::fromMilliseconds(timeout_msecs));
|
||||||
bool waitForFinish(PISystemTime timeout);
|
}
|
||||||
|
|
||||||
|
//! \~english Wait for thread finish
|
||||||
|
//! \~russian Ожидает завершения потока
|
||||||
|
bool waitForFinish(PISystemTime timeout = {});
|
||||||
|
bool waitForFinish(int timeout_msecs) DEPRECATEDM("use waitForFinish(PISystemTime)") {
|
||||||
|
return waitForFinish(PISystemTime::fromMilliseconds(timeout_msecs));
|
||||||
|
}
|
||||||
|
|
||||||
//! \~english Set necessity of lock every \a run() with internal mutex
|
//! \~english Set necessity of lock every \a run() with internal mutex
|
||||||
//! \~russian Устанавливает необходимость блокировки внутреннего мьютекса каждый \a run()
|
//! \~russian Устанавливает необходимость блокировки внутреннего мьютекса каждый \a run()
|
||||||
@@ -198,21 +233,6 @@ public:
|
|||||||
//! \handlers
|
//! \handlers
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
//! \fn bool start(int loop_delay = -1)
|
|
||||||
//! \brief
|
|
||||||
//! \~english Start thread
|
|
||||||
//! \~russian Запускает поток
|
|
||||||
|
|
||||||
//! \fn bool startOnce()
|
|
||||||
//! \brief
|
|
||||||
//! \~english Start thread without internal loop
|
|
||||||
//! \~russian Запускает поток без внутреннего цикла
|
|
||||||
|
|
||||||
//! \fn bool startOnce(ThreadFunc func)
|
|
||||||
//! \brief
|
|
||||||
//! \~english Start thread without internal loop
|
|
||||||
//! \~russian Запускает поток без внутреннего цикла
|
|
||||||
|
|
||||||
//! \fn void stop()
|
//! \fn void stop()
|
||||||
//! \brief
|
//! \brief
|
||||||
//! \~english Stop thread
|
//! \~english Stop thread
|
||||||
@@ -223,16 +243,6 @@ public:
|
|||||||
//! \~english Strongly stop thread
|
//! \~english Strongly stop thread
|
||||||
//! \~russian Жёстко прерывает поток
|
//! \~russian Жёстко прерывает поток
|
||||||
|
|
||||||
//! \fn bool waitForStart(int timeout_msecs = -1)
|
|
||||||
//! \brief
|
|
||||||
//! \~english Wait for thread start
|
|
||||||
//! \~russian Ожидает старта потока
|
|
||||||
|
|
||||||
//! \fn bool waitForFinish(int timeout_msecs = -1)
|
|
||||||
//! \brief
|
|
||||||
//! \~english Wait for thread finish
|
|
||||||
//! \~russian Ожидает завершения потока
|
|
||||||
|
|
||||||
//! \fn void lock()
|
//! \fn void lock()
|
||||||
//! \brief
|
//! \brief
|
||||||
//! \~english Lock internal mutex
|
//! \~english Lock internal mutex
|
||||||
@@ -275,7 +285,7 @@ protected:
|
|||||||
virtual void end() { ; }
|
virtual void end() { ; }
|
||||||
|
|
||||||
std::atomic_bool terminating, running_, lockRun;
|
std::atomic_bool terminating, running_, lockRun;
|
||||||
int delay_, policy_;
|
PISystemTime delay_;
|
||||||
llong tid_ = -1;
|
llong tid_ = -1;
|
||||||
void * data_ = nullptr;
|
void * data_ = nullptr;
|
||||||
mutable PIMutex thread_mutex;
|
mutable PIMutex thread_mutex;
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
#include "pithreadpoolexecutor.h"
|
#include "pithreadpoolexecutor.h"
|
||||||
|
|
||||||
|
#include "piliterals_time.h"
|
||||||
|
|
||||||
/*! \class PIThreadPoolExecutor
|
/*! \class PIThreadPoolExecutor
|
||||||
* \brief Thread pools address two different problems: they usually provide improved performance when executing large
|
* \brief Thread pools address two different problems: they usually provide improved performance when executing large
|
||||||
* numbers of asynchronous tasks, due to reduced per-task invocation overhead, and they provide a means of bounding and
|
* numbers of asynchronous tasks, due to reduced per-task invocation overhead, and they provide a means of bounding and
|
||||||
@@ -29,7 +31,7 @@
|
|||||||
PIThreadPoolExecutor::PIThreadPoolExecutor(int corePoolSize): isShutdown_(false) {
|
PIThreadPoolExecutor::PIThreadPoolExecutor(int corePoolSize): isShutdown_(false) {
|
||||||
for (int i = 0; i < corePoolSize; ++i) {
|
for (int i = 0; i < corePoolSize; ++i) {
|
||||||
PIThread * thread = new PIThread([&, i]() {
|
PIThread * thread = new PIThread([&, i]() {
|
||||||
auto runnable = taskQueue.poll(100, std::function<void()>());
|
auto runnable = taskQueue.poll(100_ms, std::function<void()>());
|
||||||
if (runnable) {
|
if (runnable) {
|
||||||
runnable();
|
runnable();
|
||||||
}
|
}
|
||||||
@@ -41,11 +43,11 @@ PIThreadPoolExecutor::PIThreadPoolExecutor(int corePoolSize): isShutdown_(false)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIThreadPoolExecutor::awaitTermination(int timeoutMs) {
|
bool PIThreadPoolExecutor::awaitTermination(PISystemTime timeout) {
|
||||||
PITimeMeasurer measurer;
|
PITimeMeasurer measurer;
|
||||||
for (size_t i = 0; i < threadPool.size(); ++i) {
|
for (size_t i = 0; i < threadPool.size(); ++i) {
|
||||||
int dif = timeoutMs - (int)measurer.elapsed_m();
|
auto dif = timeout - measurer.elapsed();
|
||||||
if (dif < 0) return false;
|
if (dif.isNegative()) return false;
|
||||||
if (!threadPool[i]->waitForFinish(dif)) return false;
|
if (!threadPool[i]->waitForFinish(dif)) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#define PITHREADPOOLEXECUTOR_H
|
#define PITHREADPOOLEXECUTOR_H
|
||||||
|
|
||||||
#include "piblockingqueue.h"
|
#include "piblockingqueue.h"
|
||||||
|
#include "pithread.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ public:
|
|||||||
|
|
||||||
bool isShutdown() const;
|
bool isShutdown() const;
|
||||||
|
|
||||||
bool awaitTermination(int timeoutMs);
|
bool awaitTermination(PISystemTime timeout);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic_bool isShutdown_;
|
std::atomic_bool isShutdown_;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "pithreadpoolloop.h"
|
#include "pithreadpoolloop.h"
|
||||||
|
|
||||||
|
#include "piliterals_time.h"
|
||||||
#include "pisysteminfo.h"
|
#include "pisysteminfo.h"
|
||||||
#include "pithread.h"
|
#include "pithread.h"
|
||||||
|
|
||||||
@@ -115,7 +116,7 @@ PIThreadPoolLoop::PIThreadPoolLoop(int thread_cnt) {
|
|||||||
PIThreadPoolLoop::~PIThreadPoolLoop() {
|
PIThreadPoolLoop::~PIThreadPoolLoop() {
|
||||||
for (auto * t: threads) {
|
for (auto * t: threads) {
|
||||||
t->stop();
|
t->stop();
|
||||||
if (!t->waitForFinish(100)) t->terminate();
|
if (!t->waitForFinish(100_ms)) t->terminate();
|
||||||
delete t;
|
delete t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,8 @@
|
|||||||
#include "pitimer.h"
|
#include "pitimer.h"
|
||||||
|
|
||||||
#include "piconditionvar.h"
|
#include "piconditionvar.h"
|
||||||
#include "piincludes_p.h"
|
#include "piliterals_time.h"
|
||||||
#include "piliterals.h"
|
#include "pithread.h"
|
||||||
#ifdef PIP_TIMER_RT
|
|
||||||
# include <csignal>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//! \addtogroup Thread
|
//! \addtogroup Thread
|
||||||
@@ -52,22 +49,22 @@
|
|||||||
//! \~russian \section PITimer_sec1 Варианты уведомления
|
//! \~russian \section PITimer_sec1 Варианты уведомления
|
||||||
//! \~english
|
//! \~english
|
||||||
//! Notify variants:
|
//! 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);
|
//! expression](https://en.cppreference.com/w/cpp/language/lambda);
|
||||||
//! * event - \a tickEvent();
|
//! * event - \a tickEvent();
|
||||||
//! * virtual function - \a tick().
|
//! * virtual function - \a tick().
|
||||||
//!
|
//!
|
||||||
//! Lambda should be [ ]( ){ } or [ ](void*){ } format.
|
//! Lambda should be [ ]( ){ } or [ ](int){ } format.
|
||||||
//!
|
//!
|
||||||
//! All these variants are equivalent, use most applicable.
|
//! All these variants are equivalent, use most applicable.
|
||||||
//! \~russian
|
//! \~russian
|
||||||
//! Варианты уведомления:
|
//! Варианты уведомления:
|
||||||
//! * "slot" - статический метод в формате void func(void * data, int delimiter) или
|
//! * "slot" - статический метод в формате void func(int delimiter) или
|
||||||
//! [лямбда-выражение](https://ru.cppreference.com/w/cpp/language/lambda);
|
//! [лямбда-выражение](https://ru.cppreference.com/w/cpp/language/lambda);
|
||||||
//! * event - \a tickEvent();
|
//! * event - \a tickEvent();
|
||||||
//! * виртуальный метод - \a tick().
|
//! * виртуальный метод - \a tick().
|
||||||
//!
|
//!
|
||||||
//! Лямбда-функция должна быть в формате [ ]( ){ } или [ ](void*){ }.
|
//! Лямбда-функция должна быть в формате [ ]( ){ } или [ ](int){ }.
|
||||||
//!
|
//!
|
||||||
//! Все варианты аналогичны друг другу, используйте самый удобный.
|
//! Все варианты аналогичны друг другу, используйте самый удобный.
|
||||||
//!
|
//!
|
||||||
@@ -89,10 +86,10 @@
|
|||||||
//! Пример:
|
//! Пример:
|
||||||
//!
|
//!
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! void tfunc(void * , int delim) {
|
//! void tfunc(int delim) {
|
||||||
//! piCout << "tick with delimiter" << delim;
|
//! piCout << "tick with delimiter" << delim;
|
||||||
//! };
|
//! };
|
||||||
//! void tfunc4(void * , int delim) {
|
//! void tfunc4(int delim) {
|
||||||
//! piCout << "tick4 with delimiter" << delim;
|
//! piCout << "tick4 with delimiter" << delim;
|
||||||
//! };
|
//! };
|
||||||
//! int main() {
|
//! int main() {
|
||||||
@@ -101,8 +98,7 @@
|
|||||||
//! timer.addDelimiter(4, tfunc4);
|
//! timer.addDelimiter(4, tfunc4);
|
||||||
//! timer.start(50);
|
//! timer.start(50);
|
||||||
//! piMSleep(200);
|
//! piMSleep(200);
|
||||||
//! timer.stop();
|
//! timer.stopAndWait();
|
||||||
//! timer.waitForFinish();
|
|
||||||
//! return 0;
|
//! return 0;
|
||||||
//! };
|
//! };
|
||||||
//! /* Result:
|
//! /* Result:
|
||||||
@@ -119,596 +115,163 @@
|
|||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
|
|
||||||
_PITimerBase::_PITimerBase() {
|
PITimer::PITimer(): PIObject() {
|
||||||
running_ = false;
|
initFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _PITimerBase::setInterval(double i) {
|
PITimer::PITimer(std::function<void(int)> func) {
|
||||||
interval_ = i;
|
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()) {
|
if (isRunning()) {
|
||||||
// piCout << "change interval runtime";
|
// piCout << "change interval runtime";
|
||||||
stop();
|
stopAndWait();
|
||||||
start();
|
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 {
|
bool PITimer::isRunning() const {
|
||||||
init();
|
return thread->isRunning();
|
||||||
return imp->running_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PITimer::isStopped() const {
|
bool PITimer::isStopping() const {
|
||||||
init();
|
return thread->isStopping();
|
||||||
return !imp->running_;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PITimer::waitForFinish(PISystemTime timeout) {
|
||||||
|
return thread->waitForFinish(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PITimer::initFirst() {
|
void PITimer::initFirst() {
|
||||||
lockRun = false;
|
thread = new PIThread([this] { threadFunc(); });
|
||||||
callEvents = true;
|
thread->setName("__S__.PITimer.thread");
|
||||||
setProperty("interval", 0.);
|
setProperty("interval", PISystemTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PITimer::init() const {
|
void PITimer::threadFunc() {
|
||||||
if (imp) return;
|
PISystemTime st_wait = m_time_next - PISystemTime::current(true);
|
||||||
switch (imp_mode) {
|
// piCout << "wait" << this << st_wait;
|
||||||
case PITimer::Pool: imp = new _PITimerImp_Pool(); break;
|
if (st_wait.abs() > m_interval_x5 || st_wait.seconds <= -5) {
|
||||||
case PITimer::ThreadRT:
|
// piCout << &thread_ << "adjust" << "...";
|
||||||
#ifdef PIP_TIMER_RT
|
adjustTimes();
|
||||||
imp = new _PITimerImp_RT();
|
// piCout << &thread_ << "adjust" << "ok";
|
||||||
break;
|
return;
|
||||||
#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);
|
|
||||||
}
|
}
|
||||||
if (!imp) return;
|
if (thread->isStopping()) return;
|
||||||
// piCout << this << "init" << imp;
|
if (st_wait.isPositive()) {
|
||||||
imp->tfunc = tickImpS;
|
thread->mutex().lock();
|
||||||
imp->parent = const_cast<PITimer *>(this);
|
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() {
|
void PITimer::adjustTimes() {
|
||||||
if (!imp) return;
|
PISystemTime cst = PISystemTime::current(true);
|
||||||
// piCout << this << "destroy" << imp;
|
if (m_time_next < cst) {
|
||||||
imp->stop();
|
int rs = (cst - m_time_next).toSeconds() / m_interval.toSeconds();
|
||||||
delete imp;
|
if (rs >= 100)
|
||||||
imp = 0;
|
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 (!isRunning()) return;
|
||||||
if (lockRun) lock();
|
if (lockRun) lock();
|
||||||
if (ret_func) ret_func(data_t, 1);
|
if (ret_func) ret_func(1);
|
||||||
tick(data_t, 1);
|
tick(1);
|
||||||
tickEvent(data_t, 1);
|
tickEvent(1);
|
||||||
if (callEvents) maybeCallQueuedEvents();
|
if (callEvents) maybeCallQueuedEvents();
|
||||||
piForeach(Delimiter & i, delims) {
|
for (Delimiter & i: delims) {
|
||||||
if (i.delim > ++(i.tick)) continue;
|
if (i.delim > ++(i.tick)) continue;
|
||||||
i.tick = 0;
|
i.tick = 0;
|
||||||
if (i.slot)
|
if (i.func)
|
||||||
i.slot(data_t, i.delim);
|
i.func(i.delim);
|
||||||
else if (ret_func)
|
else if (ret_func)
|
||||||
ret_func(data_t, i.delim);
|
ret_func(i.delim);
|
||||||
tick(data_t, i.delim);
|
tick(i.delim);
|
||||||
tickEvent(data_t, i.delim);
|
tickEvent(i.delim);
|
||||||
}
|
}
|
||||||
if (lockRun) unlock();
|
if (lockRun) unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PITimer::start() {
|
bool PITimer::start() {
|
||||||
init();
|
if (isRunning()) return true;
|
||||||
// piCout << this << "start" << imp;
|
m_interval_x5 = m_interval * 5;
|
||||||
return imp->start();
|
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) {
|
bool PITimer::start(PISystemTime interval) {
|
||||||
init();
|
if (isRunning()) stopAndWait();
|
||||||
// piCout << this << "start" << imp << interval_ms_d;
|
setInterval(interval);
|
||||||
setProperty("interval", interval_ms_d);
|
return start();
|
||||||
return imp->start(interval_ms_d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PITimer::start(int interval_ms_i) {
|
void PITimer::stopAndWait(PISystemTime timeout) {
|
||||||
return start((double)interval_ms_i);
|
stop();
|
||||||
|
thread->waitForFinish(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//! \~\details
|
void PITimer::addDelimiter(int delim, std::function<void(int)> func) {
|
||||||
//! \~english
|
delims << Delimiter(func, delim);
|
||||||
//! 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//! \~\details
|
void PITimer::addDelimiter(int delim, std::function<void()> func) {
|
||||||
//! \~english
|
delims << Delimiter([func](int) { func(); }, delim);
|
||||||
//! 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -722,14 +285,12 @@ void PITimer::removeDelimiter(int delim) {
|
|||||||
|
|
||||||
|
|
||||||
bool PITimer::restart() {
|
bool PITimer::restart() {
|
||||||
init();
|
stopAndWait();
|
||||||
imp->stop();
|
return start();
|
||||||
return imp->start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PITimer::stop() {
|
void PITimer::stop() {
|
||||||
init();
|
thread->stop();
|
||||||
// piCout << this << "stop" << imp << wait;
|
event.notifyAll();
|
||||||
return imp->stop();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,50 +26,12 @@
|
|||||||
#ifndef PITIMER_H
|
#ifndef PITIMER_H
|
||||||
#define PITIMER_H
|
#define PITIMER_H
|
||||||
|
|
||||||
#include "pithread.h"
|
#include "piconditionvar.h"
|
||||||
#include "pitime.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 {
|
class PIP_EXPORT PITimer: public PIObject {
|
||||||
PIOBJECT_SUBCLASS(PITimer, PIObject);
|
PIOBJECT_SUBCLASS(PITimer, PIObject);
|
||||||
@@ -77,118 +39,70 @@ class PIP_EXPORT PITimer: public PIObject {
|
|||||||
public:
|
public:
|
||||||
NO_COPY_CLASS(PITimer);
|
NO_COPY_CLASS(PITimer);
|
||||||
|
|
||||||
//! \~english Constructs timer with PITimer::Thread implementation
|
//! \~english Constructs timer
|
||||||
//! \~russian Создает таймер с реализацией PITimer::Thread
|
//! \~russian Создает таймер
|
||||||
explicit PITimer();
|
explicit PITimer();
|
||||||
|
|
||||||
//! \~english Timer implementations
|
//! \~english Constructs timer with method void(int)
|
||||||
//! \~russian Реализация таймера
|
//! \~russian Создает таймер с функцией void(int)
|
||||||
enum TimerImplementation {
|
explicit PITimer(std::function<void(int)> func);
|
||||||
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 "ti" implementation
|
//! \~english Constructs timer with method void()
|
||||||
//! \~russian Создает таймер с реализацией "ti"
|
//! \~russian Создает таймер с функцией void()
|
||||||
explicit PITimer(TimerImplementation ti);
|
explicit PITimer(std::function<void()> func);
|
||||||
|
|
||||||
//! \~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);
|
|
||||||
|
|
||||||
virtual ~PITimer();
|
virtual ~PITimer();
|
||||||
|
|
||||||
|
//! \~english Returns timer loop delay
|
||||||
|
//! \~russian Возвращает задержку цикла таймера
|
||||||
|
PISystemTime interval() const;
|
||||||
|
|
||||||
//! \~english Returns timer implementation
|
//! \~english Set timer loop delay
|
||||||
//! \~russian Возвращает реализацию таймера
|
//! \~russian Установить интервал таймера
|
||||||
PITimer::TimerImplementation implementation() const { return imp_mode; }
|
void setInterval(PISystemTime interval);
|
||||||
|
|
||||||
//! \~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 Returns if timer is started
|
//! \~english Returns if timer is started
|
||||||
//! \~russian Возвращает работает ли таймер
|
//! \~russian Возвращает работает ли таймер
|
||||||
bool isRunning() const;
|
bool isRunning() const;
|
||||||
|
|
||||||
//! \~english Returns if timer is not started
|
//! \~english Return if timer is stopping
|
||||||
//! \~russian Возвращает остановлен ли таймер
|
//! \~russian Возвращает останавливается ли таймер
|
||||||
bool isStopped() const;
|
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_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(bool, restart);
|
||||||
|
|
||||||
|
EVENT_HANDLER0(void, stop);
|
||||||
|
|
||||||
//! \~english Start timer with \a interval() loop delay after "delay_msecs" delay
|
//! \~english Stop timer and wait for finish.
|
||||||
//! \~russian Запускает таймер с интервалом \a interval() после ожидания "delay_msecs"
|
//! \~russian Останавливает таймер и ожидает завершения.
|
||||||
void startDeferred(double delay_ms);
|
void stopAndWait(int timeout_ms) { stopAndWait(PISystemTime::fromMilliseconds(timeout_ms)); }
|
||||||
|
|
||||||
//! \~english Start timer with "interval_msecs" loop delay after "delay_msecs" delay
|
//! \~english Stop timer and wait for finish.
|
||||||
//! \~russian Запускает таймер с интервалом "interval_msecs" после ожидания "delay_msecs"
|
//! \~russian Останавливает таймер и ожидает завершения.
|
||||||
void startDeferred(double interval_ms, double delay_ms);
|
void stopAndWait(PISystemTime timeout = {});
|
||||||
|
|
||||||
//! \~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 Set timer tick function
|
//! \~english Set timer tick function
|
||||||
//! \~russian Установить вызываемый метод
|
//! \~russian Установить вызываемый метод
|
||||||
void setSlot(TimerEvent slot) { ret_func = slot; }
|
void setSlot(std::function<void()> func) {
|
||||||
|
ret_func = [func](int) { func(); };
|
||||||
//! \~english Set timer tick function
|
|
||||||
//! \~russian Установить вызываемый метод
|
|
||||||
void setSlot(std::function<void()> slot) {
|
|
||||||
ret_func = [slot](void *, int) { slot(); };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Set timer tick function
|
//! \~english Set timer tick function
|
||||||
//! \~russian Установить вызываемый метод
|
//! \~russian Установить вызываемый метод
|
||||||
void setSlot(std::function<void(void *)> slot) {
|
void setSlot(std::function<void(int)> func) { ret_func = func; }
|
||||||
ret_func = [slot](void * d, int) { slot(d); };
|
|
||||||
}
|
|
||||||
|
|
||||||
void needLockRun(bool need) { lockRun = need; }
|
void needLockRun(bool need) { lockRun = need; }
|
||||||
EVENT_HANDLER0(void, lock) { mutex_.lock(); }
|
EVENT_HANDLER0(void, lock) { mutex_.lock(); }
|
||||||
@@ -204,13 +118,11 @@ public:
|
|||||||
|
|
||||||
//! \~english Add frequency delimiter "delim" with optional delimiter slot "slot"
|
//! \~english Add frequency delimiter "delim" with optional delimiter slot "slot"
|
||||||
//! \~russian Добавляет делитель частоты "delim" с необязательным методом "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"
|
//! \~english Add frequency delimiter "delim" with optional delimiter slot "slot"
|
||||||
//! \~russian Добавляет делитель частоты "delim" с необязательным методом "slot"
|
//! \~russian Добавляет делитель частоты "delim" с необязательным методом "slot"
|
||||||
void addDelimiter(int delim, std::function<void()> slot) {
|
void addDelimiter(int delim, std::function<void()> func);
|
||||||
delims << Delimiter([slot](void *, int) { slot(); }, delim);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Add frequency delimiter "delim" with optional delimiter slot "slot"
|
//! \~english Add frequency delimiter "delim" with optional delimiter slot "slot"
|
||||||
//! \~russian Добавляет делитель частоты "delim" с необязательным методом "slot"
|
//! \~russian Добавляет делитель частоты "delim" с необязательным методом "slot"
|
||||||
@@ -222,39 +134,15 @@ public:
|
|||||||
|
|
||||||
EVENT_HANDLER0(void, clearDelimiters) { delims.clear(); }
|
EVENT_HANDLER0(void, clearDelimiters) { delims.clear(); }
|
||||||
|
|
||||||
EVENT2(tickEvent, void *, data_, int, delimiter);
|
EVENT1(tickEvent, int, delimiter);
|
||||||
|
|
||||||
//! \handlers
|
//! \handlers
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
//! \fn void setInterval(double ms)
|
|
||||||
//! \brief
|
|
||||||
//! \~english Set timer loop delay in milliseconds
|
|
||||||
//! \~russian Установить интервал таймера "ms" миллисекунд
|
|
||||||
|
|
||||||
//! \fn bool start()
|
//! \fn bool start()
|
||||||
//! \brief
|
//! \brief
|
||||||
//! \~english Start timer with \a interval() loop delay
|
//! \~english Start timer with \a interval() loop delay
|
||||||
//! \~russian Запустить таймер с интервалом \a interval()
|
//! \~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()
|
//! \fn bool restart()
|
||||||
//! \brief
|
//! \brief
|
||||||
@@ -263,8 +151,8 @@ public:
|
|||||||
|
|
||||||
//! \fn bool stop()
|
//! \fn bool stop()
|
||||||
//! \brief
|
//! \brief
|
||||||
//! \~english Stop timer and wait for it finish
|
//! \~english Stop timer (don`t wait for finish)
|
||||||
//! \~russian Остановить таймер и дождаться остановки
|
//! \~russian Остановить таймер (не дожидается остановки)
|
||||||
|
|
||||||
//! \fn void clearDelimiters()
|
//! \fn void clearDelimiters()
|
||||||
//! \brief
|
//! \brief
|
||||||
@@ -275,16 +163,14 @@ public:
|
|||||||
//! \events
|
//! \events
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
//! \fn void tickEvent(void * data, int delimiter)
|
//! \fn void tickEvent(int delimiter)
|
||||||
//! \brief
|
//! \brief
|
||||||
//! \~english Raise on timer tick
|
//! \~english Raise on timer tick
|
||||||
//! \~russian Вызывается каждый тик таймера
|
//! \~russian Вызывается каждый тик таймера
|
||||||
//! \~\details
|
//! \~\details
|
||||||
//! \~english
|
//! \~english
|
||||||
//! "data" can be set with function \a setData() or from constructor.
|
|
||||||
//! "delimiter" is frequency delimiter, 1 for main loop.
|
//! "delimiter" is frequency delimiter, 1 for main loop.
|
||||||
//! \~russian
|
//! \~russian
|
||||||
//! "data" устанавливается методом \a setData() или в конструкторе.
|
|
||||||
//! "delimiter" - делитель частоты, 1 для основного цикла
|
//! "delimiter" - делитель частоты, 1 для основного цикла
|
||||||
|
|
||||||
|
|
||||||
@@ -292,33 +178,33 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct PIP_EXPORT Delimiter {
|
struct PIP_EXPORT Delimiter {
|
||||||
Delimiter(TimerEvent slot_ = 0, int delim_ = 1) {
|
Delimiter(std::function<void(int)> func_ = nullptr, int delim_ = 1) {
|
||||||
slot = slot_;
|
func = func_;
|
||||||
delim = delim_;
|
delim = delim_;
|
||||||
}
|
}
|
||||||
TimerEvent slot;
|
std::function<void(int)> func;
|
||||||
int delim = 0;
|
int delim = 0;
|
||||||
int tick = 0;
|
int tick = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void initFirst();
|
void initFirst();
|
||||||
void init() const;
|
void init() const;
|
||||||
void destroy();
|
|
||||||
|
|
||||||
static void tickImpS(PITimer * t) { t->tickImp(); }
|
void threadFunc();
|
||||||
void tickImp();
|
void adjustTimes();
|
||||||
|
void execTick();
|
||||||
|
|
||||||
//! Timer execution function, similar to "slot" or event \a timeout(). By default does nothing
|
//! 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;
|
PIThread * thread = nullptr;
|
||||||
std::atomic_bool lockRun, callEvents;
|
std::atomic_bool lockRun = {false}, callEvents = {true};
|
||||||
PIMutex mutex_;
|
PIMutex mutex_;
|
||||||
TimerEvent ret_func = nullptr;
|
PISystemTime m_interval, m_interval_x5;
|
||||||
TimerImplementation imp_mode = Thread;
|
PISystemTime m_time_next;
|
||||||
|
std::function<void(int)> ret_func = nullptr;
|
||||||
PIVector<Delimiter> delims;
|
PIVector<Delimiter> delims;
|
||||||
|
PIConditionVariable event;
|
||||||
mutable _PITimerBase * imp = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -194,6 +194,18 @@ public:
|
|||||||
//! \~russian Возвращает нулевое ли время
|
//! \~russian Возвращает нулевое ли время
|
||||||
bool isNull() const { return (seconds == 0) && (nanoseconds == 0); }
|
bool isNull() const { return (seconds == 0) && (nanoseconds == 0); }
|
||||||
|
|
||||||
|
//! \~english Returns if time is not null
|
||||||
|
//! \~russian Возвращает не нулевое ли время
|
||||||
|
bool isNotNull() const { return !isNull(); }
|
||||||
|
|
||||||
|
//! \~english Returns if time is greater than 0
|
||||||
|
//! \~russian Возвращает больше ли 0 время
|
||||||
|
bool isPositive() const { return (seconds >= 0) && (nanoseconds >= 0); }
|
||||||
|
|
||||||
|
//! \~english Returns if time is lesser than 0
|
||||||
|
//! \~russian Возвращает меньше ли 0 время
|
||||||
|
bool isNegative() const { return (seconds < 0) || (nanoseconds < 0); }
|
||||||
|
|
||||||
//! \~english Returns time value in seconds
|
//! \~english Returns time value in seconds
|
||||||
//! \~russian Возвращает значение времени в секундах
|
//! \~russian Возвращает значение времени в секундах
|
||||||
double toSeconds() const { return double(seconds) + nanoseconds / 1.e+9; }
|
double toSeconds() const { return double(seconds) + nanoseconds / 1.e+9; }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
#include "piliterals_time.h"
|
||||||
#include "pip.h"
|
#include "pip.h"
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
PIByteArray rnd;
|
PIByteArray rnd;
|
||||||
rnd.resize(1024 * 1024, 'x');
|
rnd.resize(1024 * 1024, 'x');
|
||||||
@@ -12,7 +12,7 @@ int main(int argc, char * argv[]) {
|
|||||||
// c.setReopenEnabled(true);
|
// c.setReopenEnabled(true);
|
||||||
PICloudServer s("127.0.0.1:10101");
|
PICloudServer s("127.0.0.1:10101");
|
||||||
auto clients = new PIVector<PICloudServer::Client *>();
|
auto clients = new PIVector<PICloudServer::Client *>();
|
||||||
CONNECTL(&tm, tickEvent, ([&](void *, int) {
|
CONNECTL(&tm, tickEvent, ([&](int) {
|
||||||
if (c.isConnected()) {
|
if (c.isConnected()) {
|
||||||
PIString str = "ping";
|
PIString str = "ping";
|
||||||
piCout << "[Client] send:" << str;
|
piCout << "[Client] send:" << str;
|
||||||
@@ -67,7 +67,7 @@ int main(int argc, char * argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
s.startThreadedRead();
|
s.startThreadedRead();
|
||||||
}
|
}
|
||||||
tm.start(1000);
|
tm.start(1_Hz);
|
||||||
PIKbdListener ls;
|
PIKbdListener ls;
|
||||||
ls.enableExitCapture(PIKbdListener::F10);
|
ls.enableExitCapture(PIKbdListener::F10);
|
||||||
ls.start();
|
ls.start();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "dispatcherserver.h"
|
#include "dispatcherserver.h"
|
||||||
|
|
||||||
|
#include "piliterals_time.h"
|
||||||
#include "piscreentiles.h"
|
#include "piscreentiles.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ DispatcherServer::~DispatcherServer() {
|
|||||||
|
|
||||||
void DispatcherServer::start() {
|
void DispatcherServer::start() {
|
||||||
eth.listen(true);
|
eth.listen(true);
|
||||||
timeout_timer.start(2000);
|
timeout_timer.start(0.5_Hz);
|
||||||
piCoutObj << "server started" << eth.readAddress();
|
piCoutObj << "server started" << eth.readAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define DISPATCHERSERVER_H
|
#define DISPATCHERSERVER_H
|
||||||
|
|
||||||
#include "cloudserver.h"
|
#include "cloudserver.h"
|
||||||
|
#include "pitimer.h"
|
||||||
|
|
||||||
class TileList;
|
class TileList;
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dispatcherserver.h"
|
#include "dispatcherserver.h"
|
||||||
#include "picrypt.h"
|
#include "picli.h"
|
||||||
|
#include "piconfig.h"
|
||||||
|
#include "pidir.h"
|
||||||
#include "piiostream.h"
|
#include "piiostream.h"
|
||||||
#include "pip.h"
|
#include "piliterals_time.h"
|
||||||
|
#include "piscreen.h"
|
||||||
|
#include "piscreentiles.h"
|
||||||
|
#include "piscreentypes.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace PICoutManipulators;
|
using namespace PICoutManipulators;
|
||||||
@@ -127,7 +132,7 @@ int main(int argc, char * argv[]) {
|
|||||||
a.children()[0]->size_policy = PIScreenTypes::Fixed;
|
a.children()[0]->size_policy = PIScreenTypes::Fixed;
|
||||||
maintile.addTile(&a);
|
maintile.addTile(&a);
|
||||||
}
|
}
|
||||||
CONNECTL(&status_timer, tickEvent, [&](void *, int) {
|
CONNECTL(&status_timer, tickEvent, [&](int) {
|
||||||
screen.lock();
|
screen.lock();
|
||||||
server.updateConnectionsTile(&conn_tl);
|
server.updateConnectionsTile(&conn_tl);
|
||||||
server.updateServersTile(&server_tl, sel_servers);
|
server.updateServersTile(&server_tl, sel_servers);
|
||||||
@@ -142,7 +147,7 @@ int main(int argc, char * argv[]) {
|
|||||||
screen.rootTile()->addTile(new TilePICout());
|
screen.rootTile()->addTile(new TilePICout());
|
||||||
screen.start();
|
screen.start();
|
||||||
server.start();
|
server.start();
|
||||||
status_timer.start(100);
|
status_timer.start(10_Hz);
|
||||||
screen.waitForFinish();
|
screen.waitForFinish();
|
||||||
} else {
|
} else {
|
||||||
PIKbdListener ls;
|
PIKbdListener ls;
|
||||||
@@ -151,7 +156,7 @@ int main(int argc, char * argv[]) {
|
|||||||
server.start();
|
server.start();
|
||||||
if (cli.hasArgument("verbose")) {
|
if (cli.hasArgument("verbose")) {
|
||||||
CONNECTU(&status_timer, tickEvent, &server, picoutStatus);
|
CONNECTU(&status_timer, tickEvent, &server, picoutStatus);
|
||||||
status_timer.start(1000);
|
status_timer.start(1_Hz);
|
||||||
}
|
}
|
||||||
WAIT_FOR_EXIT
|
WAIT_FOR_EXIT
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ int main(int argc, char * argv[]) {
|
|||||||
# define PIP_CONSOLE_STATIC_DEFINE
|
# define PIP_CONSOLE_STATIC_DEFINE
|
||||||
# include "../../libs/console/piterminal.cpp"
|
# include "../../libs/console/piterminal.cpp"
|
||||||
# include "pifile.h"
|
# include "pifile.h"
|
||||||
|
# include "piliterals_time.h"
|
||||||
# include "pip_console_export.h"
|
# include "pip_console_export.h"
|
||||||
# include "piscreentypes.h"
|
# include "piscreentypes.h"
|
||||||
# include "pisharedmemory.h"
|
# include "pisharedmemory.h"
|
||||||
@@ -164,9 +165,12 @@ public:
|
|||||||
PipeReader(): PIThread() {
|
PipeReader(): PIThread() {
|
||||||
wrote = readed = 0;
|
wrote = readed = 0;
|
||||||
msg_size = 0;
|
msg_size = 0;
|
||||||
start(1);
|
start(1_ms);
|
||||||
|
}
|
||||||
|
~PipeReader() {
|
||||||
|
stop();
|
||||||
|
if (!waitForFinish(100_ms)) terminate();
|
||||||
}
|
}
|
||||||
~PipeReader() { stop(); }
|
|
||||||
void run() {
|
void run() {
|
||||||
in.resize(PIPE_BUFFER_SIZE);
|
in.resize(PIPE_BUFFER_SIZE);
|
||||||
ReadFile(pipe, in.data(), in.size_s(), &readed, 0);
|
ReadFile(pipe, in.data(), in.size_s(), &readed, 0);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "daemon.h"
|
#include "daemon.h"
|
||||||
|
|
||||||
#include "picrypt.h"
|
#include "picrypt.h"
|
||||||
|
#include "piliterals_time.h"
|
||||||
#include "pisysteminfo.h"
|
#include "pisysteminfo.h"
|
||||||
#include "shared.h"
|
#include "shared.h"
|
||||||
|
|
||||||
@@ -23,6 +24,7 @@ Daemon::Remote::Remote(const PIString & n): PIThread() {
|
|||||||
|
|
||||||
|
|
||||||
Daemon::Remote::~Remote() {
|
Daemon::Remote::~Remote() {
|
||||||
|
term_timer.stopAndWait();
|
||||||
shellClose();
|
shellClose();
|
||||||
ft.stop();
|
ft.stop();
|
||||||
stopAndWait();
|
stopAndWait();
|
||||||
@@ -34,14 +36,14 @@ void Daemon::Remote::shellOpen() {
|
|||||||
piCoutObj << "shell open";
|
piCoutObj << "shell open";
|
||||||
term = new PITerminal();
|
term = new PITerminal();
|
||||||
term->initialize();
|
term->initialize();
|
||||||
term_timer.start(50);
|
term_timer.start(20_Hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Daemon::Remote::shellClose() {
|
void Daemon::Remote::shellClose() {
|
||||||
if (!term) return;
|
if (!term) return;
|
||||||
piCoutObj << "shell close";
|
piCoutObj << "shell close";
|
||||||
term_timer.stop();
|
term_timer.stopAndWait();
|
||||||
term->destroy();
|
term->destroy();
|
||||||
delete term;
|
delete term;
|
||||||
term = 0;
|
term = 0;
|
||||||
@@ -272,7 +274,7 @@ Daemon::Daemon(): PIPeer(pisd_prefix + PISystemInfo::instance()->hostname + "_"
|
|||||||
localft.setCRCEnabled(false);
|
localft.setCRCEnabled(false);
|
||||||
CONNECTU(&localft, sendRequest, _self, received)
|
CONNECTU(&localft, sendRequest, _self, received)
|
||||||
dtimer.addDelimiter(5);
|
dtimer.addDelimiter(5);
|
||||||
dtimer.start(200);
|
dtimer.start(5_Hz);
|
||||||
|
|
||||||
tile_root = new PIScreenTile();
|
tile_root = new PIScreenTile();
|
||||||
tile_root->direction = Vertical;
|
tile_root->direction = Vertical;
|
||||||
@@ -320,6 +322,7 @@ Daemon::Daemon(): PIPeer(pisd_prefix + PISystemInfo::instance()->hostname + "_"
|
|||||||
|
|
||||||
|
|
||||||
Daemon::~Daemon() {
|
Daemon::~Daemon() {
|
||||||
|
dtimer.stopAndWait();
|
||||||
requestCloseShell();
|
requestCloseShell();
|
||||||
PIVector<Remote *> rl = remotes.values();
|
PIVector<Remote *> rl = remotes.values();
|
||||||
piForeach(Remote * r, rl) {
|
piForeach(Remote * r, rl) {
|
||||||
@@ -547,7 +550,7 @@ void Daemon::fmActionRequest(bool remote_tile, FileManager::Action type, PIVaria
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Daemon::timerEvent(void * _d, int delim) {
|
void Daemon::timerEvent(int delim) {
|
||||||
screen->lock();
|
screen->lock();
|
||||||
list_daemons->content.clear();
|
list_daemons->content.clear();
|
||||||
availableDaemons();
|
availableDaemons();
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#define DAEMON_H
|
#define DAEMON_H
|
||||||
|
|
||||||
#include "file_manager.h"
|
#include "file_manager.h"
|
||||||
#include "pidatatransfer.h"
|
|
||||||
#include "pifiletransfer.h"
|
#include "pifiletransfer.h"
|
||||||
#include "pipeer.h"
|
#include "pipeer.h"
|
||||||
#include "piscreentiles.h"
|
#include "piscreentiles.h"
|
||||||
@@ -165,7 +164,7 @@ private:
|
|||||||
EVENT_HANDLER3(void, fmActionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data);
|
EVENT_HANDLER3(void, fmActionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data);
|
||||||
EVENT_HANDLER(void, shResizeRequest);
|
EVENT_HANDLER(void, shResizeRequest);
|
||||||
EVENT_HANDLER1(void, shKeyEvent, PIKbdListener::KeyEvent, k);
|
EVENT_HANDLER1(void, shKeyEvent, PIKbdListener::KeyEvent, k);
|
||||||
EVENT_HANDLER2(void, timerEvent, void *, _d, int, delim);
|
EVENT_HANDLER1(void, timerEvent, int, delim);
|
||||||
EVENT_HANDLER2(void, filesReceived, const PIString &, p_name, bool, ok);
|
EVENT_HANDLER2(void, filesReceived, const PIString &, p_name, bool, ok);
|
||||||
EVENT_HANDLER2(void, filesSended, const PIString &, p_name, bool, ok);
|
EVENT_HANDLER2(void, filesSended, const PIString &, p_name, bool, ok);
|
||||||
EVENT_HANDLER2(void, dirChanged, const PIString &, p_name, const PIString &, dir);
|
EVENT_HANDLER2(void, dirChanged, const PIString &, p_name, const PIString &, dir);
|
||||||
|
|||||||
@@ -21,20 +21,19 @@
|
|||||||
#include "file_manager.h"
|
#include "file_manager.h"
|
||||||
#include "picli.h"
|
#include "picli.h"
|
||||||
#include "piintrospection_server.h"
|
#include "piintrospection_server.h"
|
||||||
|
#include "piliterals_time.h"
|
||||||
#include "piprocess.h"
|
#include "piprocess.h"
|
||||||
#include "pisingleapplication.h"
|
#include "pisingleapplication.h"
|
||||||
#include "pisysteminfo.h"
|
#include "pisysteminfo.h"
|
||||||
#include "pisystemmonitor.h"
|
#include "pisystemmonitor.h"
|
||||||
#include "shared.h"
|
#include "shared.h"
|
||||||
|
|
||||||
class _Init {
|
STATIC_INITIALIZER_BEGIN
|
||||||
public:
|
randomize();
|
||||||
_Init() { randomize(); }
|
STATIC_INITIALIZER_END
|
||||||
};
|
|
||||||
_Init _pisd_init;
|
|
||||||
|
|
||||||
PISystemMonitor sys_mon;
|
PISystemMonitor sys_mon;
|
||||||
PIScreen * screen = 0;
|
PIScreen * screen = nullptr;
|
||||||
|
|
||||||
|
|
||||||
class MainMenu: public PITimer {
|
class MainMenu: public PITimer {
|
||||||
@@ -93,7 +92,7 @@ public:
|
|||||||
CONNECTU(screen, tileEvent, this, tileEvent)
|
CONNECTU(screen, tileEvent, this, tileEvent)
|
||||||
CONNECTU(screen, keyPressed, this, keyEvent)
|
CONNECTU(screen, keyPressed, this, keyEvent)
|
||||||
CONNECTU(&daemon_, menuRequest, this, menuRequest)
|
CONNECTU(&daemon_, menuRequest, this, menuRequest)
|
||||||
start(25);
|
start(40_Hz);
|
||||||
}
|
}
|
||||||
PIScreenTile * menuTile() {
|
PIScreenTile * menuTile() {
|
||||||
TileList * ret = new TileList();
|
TileList * ret = new TileList();
|
||||||
@@ -185,13 +184,19 @@ public:
|
|||||||
addrs_tl->content.clear();
|
addrs_tl->content.clear();
|
||||||
peerinfo_tl->content.clear();
|
peerinfo_tl->content.clear();
|
||||||
peermap_tl->content.clear();
|
peermap_tl->content.clear();
|
||||||
peers_tl->content << TileList::Row("this | 0 | 0 | " + PIString::fromNumber(daemon_.allPeers().size_s())
|
peers_tl->content << TileList::Row(
|
||||||
// + " [em = " + PIString::fromBool(daemon_.lockedEth()) + ",
|
"this | 0 | 0 | " + PIString::fromNumber(daemon_.allPeers().size_s())
|
||||||
//" "mm = " + PIString::fromBool(daemon_.lockedMBcasts()) + ", " "sm = " +
|
// + " [em = " + PIString::fromBool(daemon_.lockedEth()) + ",
|
||||||
//PIString::fromBool(daemon_.lockedSends()) + ", " "ms = " +
|
//" "mm = " + PIString::fromBool(daemon_.lockedMBcasts()) + ", "
|
||||||
//PIString::fromBool(daemon_.lockedMCSends()) + ", " "pm = " + PIString::fromBool(pm) + "]"
|
//"sm
|
||||||
,
|
//=
|
||||||
CellFormat());
|
//"
|
||||||
|
//+ PIString::fromBool(daemon_.lockedSends()) + ", " "ms = " +
|
||||||
|
// PIString::fromBool(daemon_.lockedMCSends()) + ", " "pm = " + PIString::fromBool(pm)
|
||||||
|
// +
|
||||||
|
// "]"
|
||||||
|
,
|
||||||
|
CellFormat());
|
||||||
piForeachC(PIPeer::PeerInfo & p, daemon_.allPeers())
|
piForeachC(PIPeer::PeerInfo & p, daemon_.allPeers())
|
||||||
peers_tl->content << TileList::Row(p.name + " | d = " + PIString::fromNumber(p.dist) + " | p = " +
|
peers_tl->content << TileList::Row(p.name + " | d = " + PIString::fromNumber(p.dist) + " | p = " +
|
||||||
PIString::fromNumber(p.ping()) + " | n = " + PIString::fromBool(p.isNeighbour()),
|
PIString::fromNumber(p.ping()) + " | n = " + PIString::fromBool(p.isNeighbour()),
|
||||||
@@ -246,7 +251,7 @@ public:
|
|||||||
}
|
}
|
||||||
screen->unlock();
|
screen->unlock();
|
||||||
}
|
}
|
||||||
void tick(void * data_, int delimiter) override {
|
void tick(int delimiter) override {
|
||||||
if (tpeerdiag->visible || tpeer->visible) updatePeerInfo();
|
if (tpeerdiag->visible || tpeer->visible) updatePeerInfo();
|
||||||
if (tinfo->visible) updateSysMon();
|
if (tinfo->visible) updateSysMon();
|
||||||
}
|
}
|
||||||
@@ -420,7 +425,7 @@ int main(int argc, char * argv[]) {
|
|||||||
ls.enableExitCapture(PIKbdListener::F10);
|
ls.enableExitCapture(PIKbdListener::F10);
|
||||||
ls.start();
|
ls.start();
|
||||||
WAIT_FOR_EXIT
|
WAIT_FOR_EXIT
|
||||||
ls.stop();
|
ls.stopAndWait();
|
||||||
} else {
|
} else {
|
||||||
screen->start();
|
screen->start();
|
||||||
screen->waitForFinish();
|
screen->waitForFinish();
|
||||||
|
|||||||
@@ -17,9 +17,11 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "picli.h"
|
||||||
#include "pidatatransfer.h"
|
#include "pidatatransfer.h"
|
||||||
|
#include "piethernet.h"
|
||||||
#include "pifiletransfer.h"
|
#include "pifiletransfer.h"
|
||||||
#include "pip.h"
|
#include "piliterals_time.h"
|
||||||
#include "piscreen.h"
|
#include "piscreen.h"
|
||||||
#include "piscreentiles.h"
|
#include "piscreentiles.h"
|
||||||
|
|
||||||
@@ -52,7 +54,7 @@ public:
|
|||||||
CONNECTU(&ft, receiveFilesFinished, this, ftevent);
|
CONNECTU(&ft, receiveFilesFinished, this, ftevent);
|
||||||
}
|
}
|
||||||
CONNECT2(void, const uchar *, ssize_t, ð, threadedReadEvent, this, received);
|
CONNECT2(void, const uchar *, ssize_t, ð, threadedReadEvent, this, received);
|
||||||
start(50);
|
start(20_Hz);
|
||||||
eth.setParameter(PIEthernet::SeparateSockets);
|
eth.setParameter(PIEthernet::SeparateSockets);
|
||||||
eth.startThreadedRead();
|
eth.startThreadedRead();
|
||||||
}
|
}
|
||||||
@@ -74,7 +76,7 @@ private:
|
|||||||
PIEthernet eth;
|
PIEthernet eth;
|
||||||
bool quet_;
|
bool quet_;
|
||||||
|
|
||||||
void tick(void *, int) override {
|
void tick(int) override {
|
||||||
if (ft.isStarted()) {
|
if (ft.isStarted()) {
|
||||||
ftevent();
|
ftevent();
|
||||||
updatePMT();
|
updatePMT();
|
||||||
|
|||||||
Reference in New Issue
Block a user