diff --git a/libs/main/core/piobject.cpp b/libs/main/core/piobject.cpp index 2297b449..95f345a1 100644 --- a/libs/main/core/piobject.cpp +++ b/libs/main/core/piobject.cpp @@ -839,7 +839,7 @@ PIObject::Deleter::Deleter() { PRIVATE->thread.setSlot([this](){ PIVector oq; PRIVATE->thread.lock(); - while(PRIVATE->obj_queue.isEmpty()) PRIVATE->cond_var.wait(PRIVATE->thread.mutex()); + PRIVATE->cond_var.wait(PRIVATE->thread.mutex()); oq.swap(PRIVATE->obj_queue); PRIVATE->thread.unlock(); for (PIObject * o : oq) deleteObject(o); @@ -851,7 +851,9 @@ PIObject::Deleter::Deleter() { PIObject::Deleter::~Deleter() { //piCout << "~Deleter ..."; PRIVATE->thread.stop(); + PRIVATE->thread.mutex().lock(); PRIVATE->cond_var.notifyAll(); + PRIVATE->thread.mutex().unlock(); PRIVATE->thread.waitForFinish(); for (PIObject * o : PRIVATE->obj_queue) deleteObject(o); //piCout << "~Deleter ok"; diff --git a/libs/main/core/piwaitevent_p.cpp b/libs/main/core/piwaitevent_p.cpp index 954aa870..72d85aee 100644 --- a/libs/main/core/piwaitevent_p.cpp +++ b/libs/main/core/piwaitevent_p.cpp @@ -95,6 +95,27 @@ bool PIWaitEvent::wait(int fd, CheckRole role) { } +bool PIWaitEvent::sleep(int us) { + if (!isCreate()) return false; +#ifdef WINDOWS + DWORD ret = WaitForSingleObjectEx(event, us / 1000, TRUE); + ResetEvent(event); + return ret == WAIT_TIMEOUT; +#else + int nfds = pipe_fd[ReadEnd] + 1; + FD_ZERO(&(fds[CheckRead])); + FD_SET(pipe_fd[ReadEnd], &(fds[CheckRead])); + timeval timeout; + timeout.tv_sec = us / 1000000; + timeout.tv_usec = us % 1000000; + int ret = ::select(nfds, &(fds[CheckRead]), nullptr, nullptr, &timeout); + int buf = 0; + while (::read(pipe_fd[ReadEnd], &buf, sizeof(buf)) > 0); + return ret == 0; +#endif +} + + void PIWaitEvent::interrupt() { if (!isCreate()) return; #ifdef WINDOWS diff --git a/libs/main/core/piwaitevent_p.h b/libs/main/core/piwaitevent_p.h index a4395eaf..3dbdb137 100644 --- a/libs/main/core/piwaitevent_p.h +++ b/libs/main/core/piwaitevent_p.h @@ -31,7 +31,7 @@ #endif -class PIWaitEvent { +class PIP_EXPORT PIWaitEvent { public: ~PIWaitEvent(); @@ -44,6 +44,7 @@ public: void create(); void destroy(); bool wait(int fd = -1, CheckRole role = CheckRead); + bool sleep(int us); // return if sleep done void interrupt(); bool isCreate() const; void * getEvent() const; // WINDOWS only diff --git a/libs/main/thread/pithread.cpp b/libs/main/thread/pithread.cpp index 0276cd25..ee5d388f 100644 --- a/libs/main/thread/pithread.cpp +++ b/libs/main/thread/pithread.cpp @@ -485,7 +485,7 @@ void __PIThreadCollection::stoppedAuto() { auto_mutex.lock(); auto_threads_.removeAll(t); auto_mutex.unlock(); - delete t; + t->deleteLater(); } diff --git a/libs/main/thread/pitimer.cpp b/libs/main/thread/pitimer.cpp index 271fcddc..bd2758f6 100644 --- a/libs/main/thread/pitimer.cpp +++ b/libs/main/thread/pitimer.cpp @@ -19,6 +19,7 @@ #include "pitimer.h" #include "piincludes_p.h" +#include "piwaitevent_p.h" #ifdef PIP_TIMER_RT # include #endif @@ -190,6 +191,7 @@ private: PIThread thread_; PISystemTime st_time, st_inc, st_wait, st_odt; + PIWaitEvent event; }; @@ -235,9 +237,10 @@ private: _PITimerImp_Thread::_PITimerImp_Thread() { thread_.setName("__S__PITimerImp_Thread::thread"); - wait_dt = 100; - wait_dd = 200; - wait_tick = 10; + wait_dt = 1000; + wait_dd = 2000; + wait_tick = 1000; + event.create(); //piCout << "_PITimerImp_Thread" << this << ", thread& =" << &thread_; //piCout << "new _PITimerImp_Thread"; } @@ -245,6 +248,7 @@ _PITimerImp_Thread::_PITimerImp_Thread() { _PITimerImp_Thread::~_PITimerImp_Thread() { stop(true); + event.destroy(); } @@ -275,6 +279,7 @@ bool _PITimerImp_Thread::startTimer(double interval_ms) { bool _PITimerImp_Thread::stopTimer(bool wait) { thread_.stop(); + event.interrupt(); if (wait) return thread_.waitForFinish(); // if (wait) // if (!thread_.waitForFinish(10)) @@ -296,10 +301,12 @@ bool _PITimerImp_Thread::threadFunc() { dwt = st_time - PISystemTime::current(true); if (wth > 0) { if (dwt.toMilliseconds() > wth + 1.) { - piMSleep(wth); + event.sleep(wth * 1000); + if (thread_.isStopping()) return false; return false; } else { - dwt.sleep(); + event.sleep(dwt.toMicroseconds()); + if (thread_.isStopping()) return false; deferred_ = false; st_time = PISystemTime::current(true); } @@ -319,10 +326,12 @@ bool _PITimerImp_Thread::threadFunc() { if (wait_tick > 0) { if (st_wait.toMilliseconds() > wait_tick + 1.) { piMSleep(wait_tick); + if (thread_.isStopping()) return false; return false; } else { //piCout << &thread_ << "sleep for" << st_wait; - st_wait.sleep(); + event.sleep(st_wait.toMicroseconds()); + if (thread_.isStopping()) return false; } } else { if (st_wait.toMilliseconds() > 0.1) diff --git a/main.cpp b/main.cpp index 73e4ad68..5ace916b 100644 --- a/main.cpp +++ b/main.cpp @@ -3,6 +3,7 @@ #include "pibytearray.h" #include "pimathbase.h" #include "pijson.h" +#include "piwaitevent_p.h" using namespace PICoutManipulators; @@ -88,6 +89,21 @@ void phase(const char * msg) { int main(int argc, char * argv[]) { piCout << "main"; + PITimer timer; + timer.setSlot([](){ + static int cnt = 0; + piCout << "tick" << ++cnt; + }); + timer.start(500); + + piSleep(1.12); + piCout << "end"; + PITimeMeasurer tm; + timer.stop(); + double tm_ms = tm.elapsed_m(); + piCout << "stop took" << tm_ms; + return 0; + /*for (int i = 0; i < count; ++i) pipes[i].create();