git-svn-id: svn://db.shs.com.ru/pip@756 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5

This commit is contained in:
2019-02-18 18:30:51 +00:00
parent 0af7eabf56
commit 217947cc89
16 changed files with 296 additions and 217 deletions

View File

@@ -1,44 +1,29 @@
#include "pip.h" #include "pip.h"
class A: public PIObject { class Base: public PIObject {
PIOBJECT(A) PIOBJECT(Base)
public: public:
A() {} EVENT_HANDLER(void, tick) {piCout << "tick";}
EVENT_HANDLER1(void, handlerA1, float, f) {piCout << "handlerA1 f" << f;}
EVENT_HANDLER1(void, handlerA2, PIString, s) {piCout << "handlerA2 s" << s;}
//uchar _[0x10];
};
class B: public PIObject {
PIOBJECT(B)
public:
B() {}
EVENT1(eventB1, float, f)
EVENT1(eventB2, PIString, s)
//uchar _[0x20];
}; };
int main() { int main() {
A a; Base b;
B b; PIConnection c;
CONNECTU(&b, eventB1, &a, handlerA1) c.configureFromConfig("d:/orders/nicirt/bin/spec_core.conf", "core");
CONNECTU(&b, eventB2, &a, handlerA2) //CONNECTU(&t, tickEvent, &b, tick);
a.dump(); piCout << "start ...";
WAIT_FOREVER c.start();
b.dump(); //t.start(500);
b.eventB1(0.33); piSleep(3);
b.eventB2("str"); //t.stop();
/*PIByteArray msg = PIByteArray::fromHex("0110f0f00001020001"); //delete t;
PIByteArray src = PIByteArray::fromHex("836f"); c.stop();
ushort s; memcpy(&s, src.data(), 2); piCout << "deleted";
//CRC_16 crc = standardCRC_16();
CRC_16 crc = CRC_16(0x8005, 0xFFFF, 0xFFFF, false); /*PIEthernet * eth = PIIODevice::createFromFullPath("eth://UDP:::192.168.0.33:16666")->cast<PIEthernet>();
piCout << PICoutManipulators::Hex << s; for (;;) {
piCout << PICoutManipulators::Hex << crc.calculate(msg);*/ eth->send(PIByteArray::fromHex("00112233445566778899"));
//PIIODevice * ser = PIIODevice::createFromFullPath("ser://COM3:9600:7:e:1 (wo,bwr)"); piSleep(1.5);
//piCout << ser << ser->constructVariant() << ser->constructFullPath(); }*/
//ser = PIIODevice::createFromVariant(ser->constructVariant());
//piCout << ser << ser->constructVariant() << ser->constructFullPath();
return 0; return 0;
} }

View File

@@ -104,6 +104,7 @@ PIConsole::PIConsole(bool startNow, PIKbdListener::KBFunc slot): PIThread() {
addTab("main"); addTab("main");
listener = new PIKbdListener(key_event, this); listener = new PIKbdListener(key_event, this);
peer_timer = new PITimer(); peer_timer = new PITimer();
peer_timer->setName("__S__.PIConsole.peer_timer");
peer = 0; peer = 0;
server_mode = pause_ = false; server_mode = pause_ = false;
state = Disconnected; state = Disconnected;

View File

@@ -216,6 +216,9 @@
#define PRIVATE (__privateinitializer__.p) #define PRIVATE (__privateinitializer__.p)
#define PRIVATEWB __privateinitializer__.p #define PRIVATEWB __privateinitializer__.p
#define NO_COPY_CLASS(name) \
explicit name(const name & ); \
void operator =(const name & );
#ifdef FREERTOS #ifdef FREERTOS
# define PIP_MIN_MSLEEP 10. # define PIP_MIN_MSLEEP 10.

View File

@@ -136,6 +136,7 @@ PICout::~PICout() {
if (fc_) applyFormat(PICoutManipulators::Default); if (fc_) applyFormat(PICoutManipulators::Default);
if (cc_) return; if (cc_) return;
newLine(); newLine();
if ((co_ & NoLock) != NoLock)
PICout::__mutex__().unlock(); PICout::__mutex__().unlock();
if (buffer_) if (buffer_)
((NotifierObject*)Notifier::object())->finished(id_, buffer_); ((NotifierObject*)Notifier::object())->finished(id_, buffer_);
@@ -427,6 +428,7 @@ void PICout::init() {
#endif #endif
buffer_ = 0; buffer_ = 0;
id_ = 0; id_ = 0;
if ((co_ & NoLock) != NoLock)
PICout::__mutex__().lock(); PICout::__mutex__().lock();
} }

View File

@@ -72,7 +72,9 @@ namespace PICoutManipulators {
AddSpaces /*! Spaces will be appear after each output */ = 0x1, AddSpaces /*! Spaces will be appear after each output */ = 0x1,
AddNewLine /*! New line will be appear after all output */ = 0x2, AddNewLine /*! New line will be appear after all output */ = 0x2,
AddQuotes /*! Each string will be quoted */ = 0x4, AddQuotes /*! Each string will be quoted */ = 0x4,
AddAll /*! All controls */ = 0xFFFFFFFF DefaultControls /*! Default controls */ = AddSpaces | AddNewLine,
AddAll /*! All controls */ = 0xFF,
NoLock /*! Don`t use mutex for output */ = 0x100,
}; };
//! \brief Enum contains output format //! \brief Enum contains output format
@@ -113,7 +115,7 @@ namespace PICoutManipulators {
class PIP_EXPORT PICout { class PIP_EXPORT PICout {
public: public:
//! Default constructor with default features (AddSpaces and AddNewLine) //! Default constructor with default features (AddSpaces and AddNewLine)
explicit PICout(PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine); explicit PICout(PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::DefaultControls);
//! Construct with external buffer and id "id". See \a Notifier for details //! Construct with external buffer and id "id". See \a Notifier for details
PICout(PIString * buffer, int id = 0, PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine); PICout(PIString * buffer, int id = 0, PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine);

View File

@@ -191,8 +191,8 @@ void PIIODevice::_init() {
#else #else
setThreadedReadBufferSize(4096); setThreadedReadBufferSize(4096);
#endif #endif
timer.setName("__S__reopen_timer"); timer.setName("__S__.PIIODevice.reopen_timer");
write_thread.setName("__S__write_thread"); write_thread.setName("__S__.PIIODevice.write_thread");
CONNECT2(void, void * , int, &timer, tickEvent, this, check_start); CONNECT2(void, void * , int, &timer, tickEvent, this, check_start);
CONNECT(void, &write_thread, started, this, write_func); CONNECT(void, &write_thread, started, this, write_func);
} }

View File

@@ -391,6 +391,8 @@ protected:
void * ret_data_; void * ret_data_;
private: private:
NO_COPY_CLASS(PIIODevice)
EVENT_HANDLER2(void, check_start, void * , data, int, delim); EVENT_HANDLER2(void, check_start, void * , data, int, delim);
EVENT_HANDLER(void, write_func); EVENT_HANDLER(void, write_func);
@@ -401,8 +403,6 @@ private:
void run(); void run();
void end() {terminate();} void end() {terminate();}
static void cacheFullPath(const PIString & full_path, const PIIODevice * d); static void cacheFullPath(const PIString & full_path, const PIIODevice * d);
explicit PIIODevice(const PIIODevice & );
void operator =(const PIIODevice & );
PITimer timer; PITimer timer;
PITimeMeasurer tm; PITimeMeasurer tm;

View File

@@ -159,6 +159,7 @@ PIEthernet::Address PIPeer::PeerInfo::fastestAddress() const {
REGISTER_DEVICE(PIPeer) REGISTER_DEVICE(PIPeer)
PIPeer::PIPeer(const PIString & n): PIIODevice(), inited__(false), eth_tcp_srv(PIEthernet::TCP_Server), eth_tcp_cli(PIEthernet::TCP_Client), diag_s(false), diag_d(false) { PIPeer::PIPeer(const PIString & n): PIIODevice(), inited__(false), eth_tcp_srv(PIEthernet::TCP_Server), eth_tcp_cli(PIEthernet::TCP_Client), diag_s(false), diag_d(false) {
sync_timer.setName("__S__.PIPeer.sync_timer");
//piCout << " PIPeer" << uint(this); //piCout << " PIPeer" << uint(this);
destroyed = false; destroyed = false;
setDebug(false); setDebug(false);

View File

@@ -1210,6 +1210,14 @@ PIConnection::Extractor::~Extractor() {
} }
PIConnection::Sender::Sender(PIConnection * parent_): parent(parent_), int_(0.f) {
setName("__S__.PIConnection.Sender");
needLockRun(true);
}
void PIConnection::Sender::tick(void * , int) { void PIConnection::Sender::tick(void * , int) {
if (parent == 0) return; if (parent == 0) return;
PIByteArray data; PIByteArray data;
@@ -1225,6 +1233,8 @@ void PIConnection::Sender::tick(void * , int) {
} }
void PIConnection::unboundExtractor(PIPacketExtractor * pe) { void PIConnection::unboundExtractor(PIPacketExtractor * pe) {
if (pe == 0) return; if (pe == 0) return;
channels_.remove(pe); channels_.remove(pe);

View File

@@ -383,7 +383,7 @@ private:
class PIP_EXPORT Sender: public PITimer { class PIP_EXPORT Sender: public PITimer {
PIOBJECT_SUBCLASS(Sender, PIObject) PIOBJECT_SUBCLASS(Sender, PIObject)
public: public:
Sender(PIConnection * parent_ = 0): parent(parent_), int_(0.f) {needLockRun(true);} Sender(PIConnection * parent_ = 0);
~Sender() {stop();} ~Sender() {stop();}
PIConnection * parent; PIConnection * parent;
PIVector<PIIODevice * > devices; PIVector<PIIODevice * > devices;

View File

@@ -206,6 +206,8 @@ public:
//! \} //! \}
private: private:
NO_COPY_CLASS(PIDiagnostics)
struct Entry { struct Entry {
Entry() {bytes_ok = bytes_fail = 0; cnt_ok = cnt_fail = 0; empty = true;} Entry() {bytes_ok = bytes_fail = 0; cnt_ok = cnt_fail = 0; empty = true;}
ullong bytes_ok; ullong bytes_ok;

View File

@@ -53,8 +53,7 @@ public:
bool isLocked() const; bool isLocked() const;
private: private:
explicit PIMutex(const PIMutex & ); NO_COPY_CLASS(PIMutex)
void operator =(const PIMutex & );
void init(); void init();
void destroy(); void destroy();

View File

@@ -34,8 +34,8 @@
#if defined(MAC_OS) || defined(BLACKBERRY) || defined(FREERTOS) #if defined(MAC_OS) || defined(BLACKBERRY) || defined(FREERTOS)
# include <pthread.h> # include <pthread.h>
#endif #endif
__THREAD_FUNC_RET__ thread_function(void * t) {PIThread::__thread_func__(t); return 0;} __THREAD_FUNC_RET__ thread_function(void * t) {((PIThread*)t)->__thread_func__(); return 0;}
__THREAD_FUNC_RET__ thread_function_once(void * t) {PIThread::__thread_func_once__(t); return 0;} __THREAD_FUNC_RET__ thread_function_once(void * t) {((PIThread*)t)->__thread_func_once__(); return 0;}
#define REGISTER_THREAD(t) __PIThreadCollection::instance()->registerThread(t) #define REGISTER_THREAD(t) __PIThreadCollection::instance()->registerThread(t)
#define UNREGISTER_THREAD(t) __PIThreadCollection::instance()->unregisterThread(t) #define UNREGISTER_THREAD(t) __PIThreadCollection::instance()->unregisterThread(t)
@@ -128,18 +128,18 @@ __PIThreadCollection * __PIThreadCollection_Initializer__::__instance__(0);
__PIThreadCollection_Initializer__::__PIThreadCollection_Initializer__() { __PIThreadCollection_Initializer__::__PIThreadCollection_Initializer__() {
count_++; count_++;
//piCout << "try create Core" << count_; //PICout(PICoutManipulators::DefaultControls) << "try create Core" << count_;
if (count_ > 1) return; if (count_ > 1) return;
//piCout << "create Core"; //PICout(PICoutManipulators::DefaultControls) << "create Core";
__instance__ = new __PIThreadCollection(); __instance__ = new __PIThreadCollection();
} }
__PIThreadCollection_Initializer__::~__PIThreadCollection_Initializer__() { __PIThreadCollection_Initializer__::~__PIThreadCollection_Initializer__() {
count_--; count_--;
//piCout << "try delete Core" << count_; //PICout(PICoutManipulators::DefaultControls) << "try delete Core" << count_;
if (count_ > 0) return; if (count_ > 0) return;
//piCout << "delete Core"; //PICout(PICoutManipulators::DefaultControls) << "delete Core";
if (__instance__ != 0) { if (__instance__ != 0) {
delete __instance__; delete __instance__;
__instance__ = 0; __instance__ = 0;
@@ -168,7 +168,6 @@ PIThread::PIThread(void * data, ThreadFunc func, bool startNow, int timer_delay)
terminating = running_ = lockRun = false; terminating = running_ = lockRun = false;
priority_ = piNormal; priority_ = piNormal;
delay_ = timer_delay; delay_ = timer_delay;
piCout << "PIThread" << this;
if (startNow) start(timer_delay); if (startNow) start(timer_delay);
} }
@@ -181,7 +180,6 @@ PIThread::PIThread(bool startNow, int timer_delay): PIObject() {
terminating = running_ = lockRun = false; terminating = running_ = lockRun = false;
priority_ = piNormal; priority_ = piNormal;
delay_ = timer_delay; delay_ = timer_delay;
piCout << "PIThread" << this;
if (startNow) start(timer_delay); if (startNow) start(timer_delay);
} }
@@ -191,11 +189,11 @@ PIThread::~PIThread() {
if (!running_ || PRIVATE->thread == 0) return; if (!running_ || PRIVATE->thread == 0) return;
#ifdef FREERTOS #ifdef FREERTOS
//void * ret(0); //void * ret(0);
//piCout << "~PIThread" << PRIVATE->thread; //PICout(PICoutManipulators::DefaultControls) << "~PIThread" << PRIVATE->thread;
//piCout << pthread_join(PRIVATE->thread, 0); //PICout(PICoutManipulators::DefaultControls) << pthread_join(PRIVATE->thread, 0);
piCout << "FreeRTOS can't terminate pthreads! waiting for stop"; PICout(PICoutManipulators::DefaultControls) << "FreeRTOS can't terminate pthreads! waiting for stop";
stop(true); stop(true);
//piCout << "stopped!"; //PICout(PICoutManipulators::DefaultControls) << "stopped!";
#else #else
#ifndef WINDOWS #ifndef WINDOWS
# ifdef ANDROID # ifdef ANDROID
@@ -204,8 +202,6 @@ PIThread::~PIThread() {
pthread_cancel(PRIVATE->thread); pthread_cancel(PRIVATE->thread);
# endif # endif
# else # else
piCout << "terminate by ~PIThread" << this;
while(1) msleep(10);
TerminateThread(PRIVATE->thread, 0); TerminateThread(PRIVATE->thread, 0);
CloseHandle(PRIVATE->thread); CloseHandle(PRIVATE->thread);
# endif # endif
@@ -214,6 +210,13 @@ PIThread::~PIThread() {
} }
void PIThread::stop(bool wait) {
PICout(PICoutManipulators::DefaultControls) << "thread" << this << "stop ..." << running_ << wait;
terminating = true;
if (wait) waitForFinish();
}
bool PIThread::start(int timer_delay) { bool PIThread::start(int timer_delay) {
if (running_) return false; if (running_) return false;
//if (terminating) waitForFinish(); //if (terminating) waitForFinish();
@@ -228,7 +231,7 @@ bool PIThread::start(int timer_delay) {
# endif # endif
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int ret = pthread_create(&PRIVATE->thread, &attr, thread_function, this); int ret = pthread_create(&PRIVATE->thread, &attr, thread_function, this);
//piCout << "pthread_create" << PRIVATE->thread; //PICout(PICoutManipulators::DefaultControls) << "pthread_create" << PRIVATE->thread;
pthread_attr_destroy(&attr); pthread_attr_destroy(&attr);
if (ret == 0) { if (ret == 0) {
# ifdef MAC_OS # ifdef MAC_OS
@@ -272,7 +275,7 @@ bool PIThread::startOnce() {
# endif # endif
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int ret = pthread_create(&(PRIVATE->thread), &attr, thread_function_once, this); int ret = pthread_create(&(PRIVATE->thread), &attr, thread_function_once, this);
//piCout << "pthread_create" << PRIVATE->thread; //PICout(PICoutManipulators::DefaultControls) << "pthread_create" << PRIVATE->thread;
pthread_attr_destroy(&attr); pthread_attr_destroy(&attr);
if (ret == 0) { if (ret == 0) {
# ifdef MAC_OS # ifdef MAC_OS
@@ -304,17 +307,18 @@ bool PIThread::startOnce() {
void PIThread::terminate() { void PIThread::terminate() {
PICout(PICoutManipulators::DefaultControls) << "thread" << this << "terminate ..." << running_;
#ifdef FREERTOS #ifdef FREERTOS
piCout << "FreeRTOS can't terminate pthreads! waiting for stop"; PICout(PICoutManipulators::DefaultControls) << "FreeRTOS can't terminate pthreads! waiting for stop";
stop(true); stop(true);
//piCout << "stopped!"; //PICout(PICoutManipulators::DefaultControls) << "stopped!";
#else #else
if (PRIVATE->thread == 0) return; if (PRIVATE->thread == 0) return;
UNREGISTER_THREAD(this); UNREGISTER_THREAD(this);
PIINTROSPECTION_UNREGISTER_THREAD(tid()); PIINTROSPECTION_UNREGISTER_THREAD(tid());
terminating = running_ = false; terminating = running_ = false;
tid_ = -1; tid_ = -1;
//piCout << "terminate" << PRIVATE->thread; //PICout(PICoutManipulators::DefaultControls) << "terminate" << PRIVATE->thread;
#ifndef WINDOWS #ifndef WINDOWS
# ifdef ANDROID # ifdef ANDROID
pthread_kill(PRIVATE->thread, SIGTERM); pthread_kill(PRIVATE->thread, SIGTERM);
@@ -325,16 +329,13 @@ void PIThread::terminate() {
//pthread_join(PRIVATE->thread, &ret); //pthread_join(PRIVATE->thread, &ret);
# endif # endif
#else #else
piCout << "terminate by terminate";
while (1) {
msleep(10);
}
TerminateThread(PRIVATE->thread, 0); TerminateThread(PRIVATE->thread, 0);
CloseHandle(PRIVATE->thread); CloseHandle(PRIVATE->thread);
#endif #endif
PRIVATE->thread = 0; PRIVATE->thread = 0;
end(); end();
#endif #endif
PICout(PICoutManipulators::DefaultControls) << "thread" << this << "terminate ok" << running_;
} }
@@ -372,7 +373,7 @@ void PIThread::setPriority(PIThread::Priority prior) {
priority_ = prior; priority_ = prior;
#ifndef WINDOWS #ifndef WINDOWS
if (!running_ || (PRIVATE->thread == 0)) return; if (!running_ || (PRIVATE->thread == 0)) return;
//piCout << "setPriority" << PRIVATE->thread; //PICout(PICoutManipulators::DefaultControls) << "setPriority" << PRIVATE->thread;
policy_ = 0; 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));
@@ -393,6 +394,7 @@ void PIThread::setPriority(PIThread::Priority prior) {
bool PIThread::waitForFinish(int timeout_msecs) { bool PIThread::waitForFinish(int timeout_msecs) {
PICout(PICoutManipulators::DefaultControls) << "thread" << this << "PIThread::waitForFinish" << running_ << terminating << timeout_msecs;
if (!running_) return true; if (!running_) return true;
if (timeout_msecs < 0) { if (timeout_msecs < 0) {
while (running_) while (running_)
@@ -420,7 +422,7 @@ bool PIThread::waitForStart(int timeout_msecs) {
} }
void PIThread::__thread_func__(void * t) { void PIThread::__thread_func__() {
#ifndef WINDOWS #ifndef WINDOWS
# if !defined(ANDROID) && !defined(FREERTOS) # if !defined(ANDROID) && !defined(FREERTOS)
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
@@ -429,61 +431,74 @@ void PIThread::__thread_func__(void * t) {
#else #else
//__PISetTimerResolution(); //__PISetTimerResolution();
#endif #endif
PIThread & ct = *((PIThread * )t);
#ifdef WINDOWS #ifdef WINDOWS
ct.tid_ = GetCurrentThreadId(); tid_ = GetCurrentThreadId();
#endif #endif
#ifdef LINUX #ifdef LINUX
ct.tid_ = gettid(); tid_ = gettid();
#endif #endif
PIINTROSPECTION_REGISTER_THREAD(ct.tid(), ct.priority(), ct.name()); PIINTROSPECTION_REGISTER_THREAD(tid(), priority(), name());
REGISTER_THREAD(&ct); REGISTER_THREAD(this);
ct.running_ = true; running_ = true;
if (ct.lockRun) ct.mutex_.lock(); if (lockRun) mutex_.lock();
ct.begin(); begin();
if (ct.lockRun) ct.mutex_.unlock(); if (lockRun) mutex_.unlock();
ct.started(); started();
while (!ct.terminating) { while (!terminating) {
ct.maybeCallQueuedEvents(); PICout(PICoutManipulators::DefaultControls) << "thread" << this << "queued" << "...";
if (ct.lockRun) ct.mutex_.lock(); maybeCallQueuedEvents();
// piCout << "thread" << ct.name() << "..." << ct.lockRun; PICout(PICoutManipulators::DefaultControls) << "thread" << this << "queued" << "ok";
ct.run(); PICout(PICoutManipulators::DefaultControls) << "thread" << this << "lock" << "...";
//printf("thread %p tick\n", &ct); if (lockRun) mutex_.lock();
if (ct.ret_func != 0) ct.ret_func(ct.data_); PICout(PICoutManipulators::DefaultControls) << "thread" << this << "lock" << "ok";
if (ct.lockRun) ct.mutex_.unlock(); PICout(PICoutManipulators::DefaultControls) << "thread" << this << "run" << "...";
// piCout << "thread" << ct.name() << "done"; run();
if (ct.delay_ > 0) { PICout(PICoutManipulators::DefaultControls) << "thread" << this << "run" << "ok";
ct.tmr_.reset(); //printf("thread %p tick\n", this);
PICout(PICoutManipulators::DefaultControls) << "thread" << this << "ret_func" << "...";
if (ret_func != 0) ret_func(data_);
PICout(PICoutManipulators::DefaultControls) << "thread" << this << "ret_func" << "ok";
PICout(PICoutManipulators::DefaultControls) << "thread" << this << "unlock" << "...";
if (lockRun) mutex_.unlock();
PICout(PICoutManipulators::DefaultControls) << "thread" << this << "unlock" << "ok";
PICout(PICoutManipulators::DefaultControls) << "thread" << this << "wait" << "...";
if (delay_ > 0) {
tmr_.reset();
double sl(0.); double sl(0.);
while (1) { while (1) {
sl = piMind(ct.delay_ - ct.tmr_.elapsed_m(), PIP_MIN_MSLEEP); sl = piMind(delay_ - tmr_.elapsed_m(), PIP_MIN_MSLEEP);
#ifdef WINDOWS #ifdef WINDOWS
/*if (sl <= 1. && sl >= 0.) { /*if (sl <= 1. && sl >= 0.) {
piMSleep(PIP_MIN_MSLEEP); piMSleep(PIP_MIN_MSLEEP);
continue; continue;
}*/ }*/
#endif #endif
//printf("%f %f %f\n", double(ct.delay_), ct.tmr_.elapsed_m(), sl); //printf("%f %f %f\n", double(delay_), tmr_.elapsed_m(), sl);
if (ct.terminating) break; if (terminating) break;
if (sl <= 0.) break; if (sl <= 0.) break;
piMSleep(sl); piMSleep(sl);
} }
} }
PICout(PICoutManipulators::DefaultControls) << "thread" << this << "wait" << "ok";
} }
ct.stopped(); PICout(PICoutManipulators::DefaultControls) << "thread" << this << "stop" << "...";
if (ct.lockRun) ct.mutex_.lock(); stopped();
ct.end(); PICout(PICoutManipulators::DefaultControls) << "thread" << this << "stop" << "ok";
if (ct.lockRun) ct.mutex_.unlock(); if (lockRun) mutex_.lock();
ct.terminating = ct.running_ = false; PICout(PICoutManipulators::DefaultControls) << "thread" << this << "end" << "...";
ct.tid_ = -1; end();
PICout(PICoutManipulators::DefaultControls) << "thread" << this << "stop" << "ok";
if (lockRun) mutex_.unlock();
terminating = running_ = false;
tid_ = -1;
PICout(PICoutManipulators::DefaultControls) << "thread" << this << "exit";
//cout << "thread " << t << " exiting ... " << endl; //cout << "thread " << t << " exiting ... " << endl;
//piCout << "pthread_exit" << (ct.__privateinitializer__.p)->thread; //PICout(PICoutManipulators::DefaultControls) << "pthread_exit" << (__privateinitializer__.p)->thread;
UNREGISTER_THREAD(&ct); UNREGISTER_THREAD(this);
PIINTROSPECTION_UNREGISTER_THREAD(ct.tid()); PIINTROSPECTION_UNREGISTER_THREAD(tid());
piCout << "pthread_exit" << &ct;
#ifndef WINDOWS #ifndef WINDOWS
pthread_detach((ct.__privateinitializer__.p)->thread); pthread_detach((__privateinitializer__.p)->thread);
(ct.__privateinitializer__.p)->thread = 0; (__privateinitializer__.p)->thread = 0;
#endif #endif
#ifndef WINDOWS #ifndef WINDOWS
pthread_exit(0); pthread_exit(0);
@@ -497,7 +512,7 @@ void PIThread::__thread_func__(void * t) {
} }
void PIThread::__thread_func_once__(void * t) { void PIThread::__thread_func_once__() {
#ifndef WINDOWS #ifndef WINDOWS
# if !defined(ANDROID) && !defined(FREERTOS) # if !defined(ANDROID) && !defined(FREERTOS)
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
@@ -506,33 +521,32 @@ void PIThread::__thread_func_once__(void * t) {
#else #else
//__PISetTimerResolution(); //__PISetTimerResolution();
#endif #endif
PIThread & ct = *((PIThread * )t);
#ifdef WINDOWS #ifdef WINDOWS
ct.tid_ = GetCurrentThreadId(); tid_ = GetCurrentThreadId();
#endif #endif
#ifdef LINUX #ifdef LINUX
ct.tid_ = gettid(); tid_ = gettid();
#endif #endif
PIINTROSPECTION_REGISTER_THREAD(ct.tid(), ct.priority(), ct.name()); PIINTROSPECTION_REGISTER_THREAD(tid(), priority(), name());
REGISTER_THREAD(&ct); REGISTER_THREAD(this);
ct.running_ = true; running_ = true;
ct.begin(); begin();
ct.started(); started();
if (ct.lockRun) ct.mutex_.lock(); if (lockRun) mutex_.lock();
ct.run(); run();
if (ct.ret_func != 0) ct.ret_func(ct.data_); if (ret_func != 0) ret_func(data_);
if (ct.lockRun) ct.mutex_.unlock(); if (lockRun) mutex_.unlock();
ct.stopped(); stopped();
ct.end(); end();
ct.terminating = ct.running_ = false; terminating = running_ = false;
ct.tid_ = -1; tid_ = -1;
//cout << "thread " << t << " exiting ... " << endl; //cout << "thread " << t << " exiting ... " << endl;
//piCout << "pthread_exit" << (ct.__privateinitializer__.p)->thread; //PICout(PICoutManipulators::DefaultControls) << "pthread_exit" << (__privateinitializer__.p)->thread;
UNREGISTER_THREAD(&ct); UNREGISTER_THREAD(this);
PIINTROSPECTION_UNREGISTER_THREAD(ct.tid()); PIINTROSPECTION_UNREGISTER_THREAD(tid());
#ifndef WINDOWS #ifndef WINDOWS
pthread_detach((ct.__privateinitializer__.p)->thread); pthread_detach((__privateinitializer__.p)->thread);
(ct.__privateinitializer__.p)->thread = 0; (__privateinitializer__.p)->thread = 0;
#endif #endif
#ifndef WINDOWS #ifndef WINDOWS
pthread_exit(0); pthread_exit(0);

View File

@@ -82,12 +82,12 @@ public:
EVENT_HANDLER0(bool, start) {return start(-1);} EVENT_HANDLER0(bool, start) {return start(-1);}
EVENT_HANDLER1(bool, start, int, timer_delay); EVENT_HANDLER1(bool, start, int, timer_delay);
bool start(ThreadFunc func) {ret_func = func; return start(-1);} bool start(ThreadFunc func) {return start(func, -1);}
bool start(ThreadFunc func, int timer_delay) {ret_func = func; return start(timer_delay);} bool start(ThreadFunc func, int timer_delay) {ret_func = func; return start(timer_delay);}
EVENT_HANDLER0(bool, startOnce); EVENT_HANDLER0(bool, startOnce);
EVENT_HANDLER1(bool, startOnce, ThreadFunc, func) {ret_func = func; return startOnce();} EVENT_HANDLER1(bool, startOnce, ThreadFunc, func) {ret_func = func; return startOnce();}
EVENT_HANDLER0(void, stop) {stop(false);} EVENT_HANDLER0(void, stop) {stop(false);}
EVENT_HANDLER1(void, stop, bool, wait) {terminating = true; if (wait) waitForFinish();} EVENT_HANDLER1(void, stop, bool, wait);
EVENT_HANDLER0(void, terminate); EVENT_HANDLER0(void, terminate);
//! \brief Set common data passed to external function //! \brief Set common data passed to external function
@@ -126,8 +126,8 @@ public:
//! \brief Returns thread ID //! \brief Returns thread ID
llong tid() const {return tid_;} llong tid() const {return tid_;}
static void __thread_func__(void*); void __thread_func__();
static void __thread_func_once__(void*); void __thread_func_once__();
EVENT(started) EVENT(started)
EVENT(stopped) EVENT(stopped)
@@ -221,6 +221,10 @@ protected:
PIThread::Priority priority_; PIThread::Priority priority_;
ThreadFunc ret_func; ThreadFunc ret_func;
PRIVATE_DECLARATION PRIVATE_DECLARATION
private:
NO_COPY_CLASS(PIThread)
}; };

View File

@@ -18,7 +18,7 @@
*/ */
#include "pitimer.h" #include "pitimer.h"
#include <stdio.h> #include "piincludes_p.h"
#ifdef PIP_TIMER_RT #ifdef PIP_TIMER_RT
# include <csignal> # include <csignal>
#endif #endif
@@ -73,6 +73,7 @@ bool _PITimerBase::start(double interval_ms) {
if (isRunning()) stop(true); if (isRunning()) stop(true);
deferred_ = false; deferred_ = false;
setInterval(interval_ms); setInterval(interval_ms);
piCout << "_PITimerBase::startTimer"<<interval_ms<<"...";
running_ = startTimer(interval_ms); running_ = startTimer(interval_ms);
return running_; return running_;
} }
@@ -99,15 +100,16 @@ void _PITimerBase::startDeferred(double interval_ms, double delay_ms) {
bool _PITimerBase::stop(bool wait) { bool _PITimerBase::stop(bool wait) {
piCout << "_PITimerBase::stop" << isRunning(); //piCout << GetCurrentThreadId() << "_PITimerBase::stop" << wait << isRunning();
if (!isRunning()) return true; if (!isRunning()) return true;
piCout << "_PITimerBase::stopTimer"; piCout << "_PITimerBase::stopTimer ...";
running_ = !stopTimer(wait); running_ = !stopTimer(wait);
return !running_; return !running_;
} }
class _PITimerImp_Thread: public _PITimerBase { class _PITimerImp_Thread: public _PITimerBase {
public: public:
_PITimerImp_Thread(); _PITimerImp_Thread();
@@ -147,7 +149,7 @@ private:
class _PITimerImp_Pool: public _PITimerImp_Thread { class _PITimerImp_Pool: public _PITimerImp_Thread {
public: public:
_PITimerImp_Pool(); _PITimerImp_Pool();
virtual ~_PITimerImp_Pool() {} virtual ~_PITimerImp_Pool() {stop(true);}
private: private:
class Pool: public PIThread { class Pool: public PIThread {
public: public:
@@ -172,14 +174,13 @@ _PITimerImp_Thread::_PITimerImp_Thread() {
wait_dt = 100; wait_dt = 100;
wait_dd = 200; wait_dd = 200;
wait_tick = 10; wait_tick = 10;
piCout << "new _PITimerImp_Thread" << &thread_ << this; piCout << "_PITimerImp_Thread" << this << ", thread& =" << &thread_;
//piCout << "new _PITimerImp_Thread";
} }
_PITimerImp_Thread::~_PITimerImp_Thread() { _PITimerImp_Thread::~_PITimerImp_Thread() {
piCout << "~_PITimerImp_Thread ..." << &thread_ << this; stop(true);
thread_.stop(true);
piCout << "~_PITimerImp_Thread done" << &thread_ << this;
} }
@@ -209,7 +210,6 @@ bool _PITimerImp_Thread::startTimer(double interval_ms) {
bool _PITimerImp_Thread::stopTimer(bool wait) { bool _PITimerImp_Thread::stopTimer(bool wait) {
piCout << "stop timer..." << &thread_ << this;
#ifndef FREERTOS #ifndef FREERTOS
thread_.stop(true); thread_.stop(true);
#else #else
@@ -219,19 +219,12 @@ bool _PITimerImp_Thread::stopTimer(bool wait) {
if (thread_.isRunning()) if (thread_.isRunning())
thread_.terminate(); thread_.terminate();
#endif #endif
piCout << "stop timer done!" << this << st_wait;
return true; return true;
} }
bool _PITimerImp_Thread::threadFunc() { bool _PITimerImp_Thread::threadFunc() {
//piCout << "threadFunc"; if (!running_) return false;
//printf("threadFunc\n");
if (!running_) {
//piCout << "threadFunc 1";
//printf("threadFunc 1");
return false;
}
if (deferred_) { if (deferred_) {
PISystemTime dwt; PISystemTime dwt;
int wth(wait_dt); int wth(wait_dt);
@@ -242,69 +235,46 @@ bool _PITimerImp_Thread::threadFunc() {
dwt = st_time - PISystemTime::current(true); dwt = st_time - PISystemTime::current(true);
if (wth > 0) { if (wth > 0) {
if (dwt.toMilliseconds() > wth + 1.) { if (dwt.toMilliseconds() > wth + 1.) {
//printf("wait 2\n"); piMSleep(wth);
//piCout << "wait 2" << this << dwt;
msleep(wth);
//printf("threadFunc 2\n");
//piCout << "threadFunc 2";
return false; return false;
} else { } else {
//piCout << "wait 3" << this << dwt;
//printf("wait 3\n");
dwt.sleep(); dwt.sleep();
deferred_ = false; deferred_ = false;
st_time = PISystemTime::current(true); st_time = PISystemTime::current(true);
} }
} else { } else {
if (dwt.toMilliseconds() > 0.1) { if (dwt.toMilliseconds() > 0.1)
//piCout << "threadFunc 3";
//printf("threadFunc 3\n");
return false; return false;
} }
} }
}
st_wait = st_time - PISystemTime::current(true); st_wait = st_time - PISystemTime::current(true);
//piCout << "wait" << this << st_wait; //piCout << "wait" << this << st_wait;
if (st_wait.abs() > st_odt || st_wait.seconds <= -5) { if (st_wait.abs() > st_odt || st_wait.seconds <= -5) {
piCout << &thread_ << "adjust" << "...";
adjustTimes(); adjustTimes();
//piCout << "threadFunc 4"; piCout << &thread_ << "adjust" << "ok";
//printf("threadFunc 4\n");
return true; return true;
} }
if (wait_tick > 0) { if (wait_tick > 0) {
if (st_wait.toMilliseconds() > wait_tick + 1.) { if (st_wait.toMilliseconds() > wait_tick + 1.) {
//piCout << "wait 5" << this << wait_tick; piMSleep(wait_tick);
//printf("wait 5 %d\n", wait_tick);
//fflush(stdout);
msleep(wait_tick);
//piCout << "threadFunc 5";
//printf("threadFunc 5\n");
//fflush(stdout);
return false; return false;
} else { } else {
//piCout << "wait 6" << this << st_wait; piCout << &thread_ << "sleep for" << st_wait;
//printf("wait 6 %f\n" , st_wait.toMicroseconds());
st_wait.sleep(); st_wait.sleep();
} }
} else { } else {
if (st_wait.toMilliseconds() > 0.1) { if (st_wait.toMilliseconds() > 0.1)
//piCout << "threadFunc 6";
//printf("threadFunc 6\n");
return false; return false;
} }
}
st_time += st_inc; st_time += st_inc;
if (!parent->isPIObject()) { if (!parent->isPIObject()) {
piCout << "Achtung! PITimer \"parent\" is not PIObject!"; piCout << "Achtung! PITimer \"parent\" is not PIObject!";
//piCout << "threadFunc 7";
printf("threadFunc 7\n");
return false; return false;
} }
//piCout << "timer tick"; piCout << &thread_ << "tfunc" << "...";
//printf("timer tick\n");
tfunc(parent); tfunc(parent);
//piCout << "threadFunc 8"; piCout << &thread_ << "tfunc" << "ok";
//printf("threadFunc 8\n");
return true; return true;
} }
@@ -529,18 +499,42 @@ PITimer::~PITimer() {
} }
double PITimer::interval() const {
init();
return imp->interval_;
}
void PITimer::setInterval(double ms) {
init();
setProperty("interval", ms);
imp->setInterval(ms);
}
bool PITimer::isRunning() const {
init();
return imp->running_;
}
bool PITimer::isStopped() const {
init();
return !imp->running_;
}
void PITimer::initFirst() { void PITimer::initFirst() {
setProperty("interval", 0.);
lockRun = false; lockRun = false;
data_t = 0; data_t = 0;
ret_func = 0; ret_func = 0;
imp = 0; imp = 0;
init(); setProperty("interval", 0.);
} }
void PITimer::init() { void PITimer::init() const {
destroy(); if (imp) return;
switch (imp_mode) { switch (imp_mode) {
case PITimer::Pool: imp = new _PITimerImp_Pool(); break; case PITimer::Pool: imp = new _PITimerImp_Pool(); break;
case PITimer::ThreadRT: case PITimer::ThreadRT:
@@ -553,16 +547,17 @@ void PITimer::init() {
case PITimer::Thread: imp = new _PITimerImp_Thread(); break; case PITimer::Thread: imp = new _PITimerImp_Thread(); break;
default: piCout << "Fatal: invalid implementation() of" << this << "!"; assert(0); default: piCout << "Fatal: invalid implementation() of" << this << "!"; assert(0);
} }
if (imp == 0) return; if (!imp) return;
piCout << this << "init" << imp;
imp->tfunc = tickImpS; imp->tfunc = tickImpS;
imp->parent = this; imp->parent = const_cast<PITimer*>(this);
} }
void PITimer::destroy() { void PITimer::destroy() {
//piCout << "destroy" << this << imp; if (!imp) return;
if (imp == 0) return; piCout << this << "destroy" << imp;
imp->stop(true); ///BUG: WTF FreeRTOS segfault on this! imp->stop(false); ///BUG: WTF FreeRTOS segfault on this!
delete imp; delete imp;
imp = 0; imp = 0;
} }
@@ -571,15 +566,15 @@ void PITimer::destroy() {
void PITimer::tickImp() { void PITimer::tickImp() {
if (!isRunning()) return; if (!isRunning()) return;
if (lockRun) lock(); if (lockRun) lock();
if (ret_func != 0) ret_func(data_t, 1); if (ret_func) ret_func(data_t, 1);
tick(data_t, 1); tick(data_t, 1);
tickEvent(data_t, 1); tickEvent(data_t, 1);
maybeCallQueuedEvents(); maybeCallQueuedEvents();
piForeach (Delimiter & i, delims) { piForeach (Delimiter & i, delims) {
if (i.delim > ++(i.tick)) continue; if (i.delim > ++(i.tick)) continue;
i.tick = 0; i.tick = 0;
if (i.slot != 0) i.slot(data_t, i.delim); if (i.slot) i.slot(data_t, i.delim);
else if (ret_func != 0) ret_func(data_t, i.delim); else if (ret_func) ret_func(data_t, i.delim);
tick(data_t, i.delim); tick(data_t, i.delim);
tickEvent(data_t, i.delim); tickEvent(data_t, i.delim);
} }
@@ -587,6 +582,67 @@ void PITimer::tickImp() {
} }
bool PITimer::start() {
piCout << this << "start" << imp;
return imp->start();
}
bool PITimer::start(double interval_ms_d) {
init();
piCout << this << "start" << imp << interval_ms_d;
setProperty("interval", interval_ms_d);
return imp->start(interval_ms_d);
}
bool PITimer::start(int interval_ms_i) {
return start((double)interval_ms_i);
}
void PITimer::startDeferred(double delay_ms) {
init();
imp->startDeferred(delay_ms);
}
void PITimer::startDeferred(double interval_ms, double delay_ms) {
init();
imp->startDeferred(interval_ms, delay_ms);
}
void PITimer::startDeferred(PIDateTime start_datetime) {
startDeferred(imp->interval_, start_datetime);
}
void PITimer::startDeferred(double interval_ms, PIDateTime start_datetime) {
init();
imp->startDeferred(interval_ms, start_datetime);
}
bool PITimer::restart() {
init();
imp->stop(true);
return imp->start();
}
bool PITimer::stop() {
return stop(true);
}
bool PITimer::stop(bool wait) {
init();
piCout << this << "stop" << imp << wait;
return imp->stop(wait);
}
bool PITimer::waitForFinish(int timeout_msecs) { bool PITimer::waitForFinish(int timeout_msecs) {
if (timeout_msecs < 0) { if (timeout_msecs < 0) {
while (isRunning()) while (isRunning())

View File

@@ -103,45 +103,45 @@ public:
PITimer::TimerImplementation implementation() const {return imp_mode;} PITimer::TimerImplementation implementation() const {return imp_mode;}
//! \brief Returns timer loop delay in milliseconds //! \brief Returns timer loop delay in milliseconds
double interval() const {return imp->interval_;} double interval() const;
//! \brief Set timer loop delay in milliseconds //! \brief Set timer loop delay in milliseconds
EVENT_HANDLER1(void, setInterval, double, ms) {setProperty("interval", ms); imp->setInterval(ms);} EVENT_HANDLER1(void, setInterval, double, ms);
//! \brief Returns if timer is started //! \brief Returns if timer is started
bool isRunning() const {return imp->running_;} bool isRunning() const;
//! \brief Returns if timer is not started //! \brief Returns if timer is not started
bool isStopped() const {return !imp->running_;} bool isStopped() const;
EVENT_HANDLER0(bool, start) {return imp->start();} EVENT_HANDLER0(bool, start);
EVENT_HANDLER1(bool, start, double, interval_ms_d) {setProperty("interval", interval_ms_d); return imp->start(interval_ms_d);} EVENT_HANDLER1(bool, start, double, interval_ms_d);
bool start(int interval_ms_i) {setProperty("interval", double(interval_ms_i)); return imp->start(double(interval_ms_i));} bool start(int interval_ms_i);
EVENT_HANDLER0(bool, restart) {imp->stop(true); return imp->start();} EVENT_HANDLER0(bool, restart);
/** \brief Start timer with \b interval() loop delay after \b delay_msecs delay. /** \brief Start timer with \b interval() loop delay after \b delay_msecs delay.
* \details Timer wait \b delay_msecs milliseconds and then normally starts with * \details Timer wait \b delay_msecs milliseconds and then normally starts with
* \b interval() loop delay. */ * \b interval() loop delay. */
void startDeferred(double delay_ms) {imp->startDeferred(delay_ms);} void startDeferred(double delay_ms);
/** \brief Start timer with \b interval_msecs loop delay after \b delay_msecs delay. /** \brief Start timer with \b interval_msecs loop delay after \b delay_msecs delay.
* \details Timer wait \b delay_msecs milliseconds and then normally starts with * \details Timer wait \b delay_msecs milliseconds and then normally starts with
* \b interval_msecs loop delay. */ * \b interval_msecs loop delay. */
void startDeferred(double interval_ms, double delay_ms) {imp->startDeferred(interval_ms, delay_ms);} void startDeferred(double interval_ms, double delay_ms);
/** \brief Start timer with \b interval() loop delay after \b start_datetime date and time. /** \brief Start timer with \b interval() loop delay after \b start_datetime date and time.
* \details Timer wait until \b start_datetime and then normally starts with * \details Timer wait until \b start_datetime and then normally starts with
* \b interval() loop delay. */ * \b interval() loop delay. */
void startDeferred(PIDateTime start_datetime) {startDeferred(imp->interval_, start_datetime);} void startDeferred(PIDateTime start_datetime);
/** \brief Start timer with \b interval_msecs loop delay after \b start_datetime date and time. /** \brief Start timer with \b interval_msecs loop delay after \b start_datetime date and time.
* \details Timer wait until \b start_datetime and then normally starts with * \details Timer wait until \b start_datetime and then normally starts with
* \b interval_msecs loop delay. */ * \b interval_msecs loop delay. */
void startDeferred(double interval_ms, PIDateTime start_datetime) {imp->startDeferred(interval_ms, start_datetime);} void startDeferred(double interval_ms, PIDateTime start_datetime);
EVENT_HANDLER0(bool, stop) {return imp->stop(true);} EVENT_HANDLER0(bool, stop);
EVENT_HANDLER1(bool, stop, bool, wait) {return imp->stop(wait);} EVENT_HANDLER1(bool, stop, bool, wait);
bool waitForFinish() {return waitForFinish(-1);} bool waitForFinish() {return waitForFinish(-1);}
bool waitForFinish(int timeout_msecs); bool waitForFinish(int timeout_msecs);
@@ -222,7 +222,7 @@ protected:
}; };
void initFirst(); void initFirst();
void init(); void init() const;
void destroy(); void destroy();
static void tickImpS(PITimer * t) {t->tickImp();} static void tickImpS(PITimer * t) {t->tickImp();}
@@ -239,11 +239,11 @@ protected:
TimerImplementation imp_mode; TimerImplementation imp_mode;
PIVector<Delimiter> delims; PIVector<Delimiter> delims;
_PITimerBase * imp; mutable _PITimerBase * imp;
private: private:
explicit PITimer(const PITimer & ); NO_COPY_CLASS(PITimer)
void operator =(const PITimer & );
}; };