diff --git a/CMakeLists.txt b/CMakeLists.txt index 40677396..d178844d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0017 NEW) # need include() with .cmake project(PIP) set(PIP_MAJOR 4) -set(PIP_MINOR 5) +set(PIP_MINOR 6) set(PIP_REVISION 0) set(PIP_SUFFIX ) set(PIP_COMPANY SHS) diff --git a/libs/main/text/pistring.cpp b/libs/main/text/pistring.cpp index 03952a44..e9b37fad 100644 --- a/libs/main/text/pistring.cpp +++ b/libs/main/text/pistring.cpp @@ -492,7 +492,8 @@ void PIString::buildData(const char * cp) const { std::string u8str = ucs2conv.to_bytes((char16_t *)d.data(), (char16_t *)d.data() + d.size()); data_ = (char *)malloc(u8str.size() + 1); strcpy(data_, u8str.c_str()); - data_size_ = u8str.size(); + data_[u8str.size()] = '\0'; + data_size_ = u8str.size(); # endif #endif } diff --git a/libs/main/thread/pithread.cpp b/libs/main/thread/pithread.cpp index b9abf861..4cda498b 100644 --- a/libs/main/thread/pithread.cpp +++ b/libs/main/thread/pithread.cpp @@ -21,6 +21,7 @@ #include "piincludes_p.h" #include "piintrospection_threads.h" +#include "piliterals_time.h" #include "pitime.h" #include "pitranslator.h" #ifndef MICRO_PIP @@ -827,26 +828,14 @@ bool PIThread::waitForFinish(PISystemTime timeout) { // timeout_msecs; if (!running_) return true; if (timeout.isNull()) { - while (running_) { - piMinSleep(); -#ifdef WINDOWS - if (!isExists(PRIVATE->thread)) { - unlock(); - return true; - } -#endif + for (;;) { + if (_waitForFinish(100_ms)) break; } return true; } tmf_.reset(); - while (running_ && tmf_.elapsed() < timeout) { - piMinSleep(); -#ifdef WINDOWS - if (!isExists(PRIVATE->thread)) { - unlock(); - return true; - } -#endif + while (tmf_.elapsed() < timeout) { + if (_waitForFinish(100_ms)) return true; } return tmf_.elapsed() < timeout; } @@ -919,10 +908,11 @@ void PIThread::_endThread() { PIScopeExitCall ec([this] { terminating = running_ = false; tid_ = -1; + state_mutex.lock(); + state_var.notifyAll(); + state_mutex.unlock(); }); - // while (PRIVATE->starting) - // piMinSleep(); - // PICout(PICoutManipulators::DefaultControls) << "thread" << this << "stop" << "..."; + // PICout(PICoutManipulators::DefaultControls) << "thread" << this << "stop" << "..."; stopped(); // PICout(PICoutManipulators::DefaultControls) << "thread" << this << "stop" << "ok"; if (lockRun) thread_mutex.lock(); @@ -1084,3 +1074,19 @@ void PIThread::setThreadName() { # endif #endif } + + +bool PIThread::_waitForFinish(PISystemTime max_tm) { + if (!running_) return true; + state_mutex.lock(); + state_var.waitFor(state_mutex, max_tm); + state_mutex.unlock(); + if (!running_) return true; +#ifdef WINDOWS + if (!isExists(PRIVATE->thread)) { + unlock(); + return true; + } +#endif + return false; +} diff --git a/libs/main/thread/pithread.h b/libs/main/thread/pithread.h index d9f7847b..e9d1dc4f 100644 --- a/libs/main/thread/pithread.h +++ b/libs/main/thread/pithread.h @@ -26,6 +26,7 @@ #ifndef PITHREAD_H #define PITHREAD_H +#include "piconditionvar.h" #include "piinit.h" #include "pimutex.h" #include "piobject.h" @@ -286,10 +287,11 @@ protected: PISystemTime delay_; llong tid_ = -1; void * data_ = nullptr; - mutable PIMutex thread_mutex; + mutable PIMutex thread_mutex, state_mutex; PITimeMeasurer tmf_, tms_, tmr_; PIThread::Priority priority_ = piNormal; ThreadFunc ret_func = nullptr; + PIConditionVariable state_var; PRIVATE_DECLARATION(PIP_EXPORT) private: @@ -297,6 +299,7 @@ private: void _beginThread(); void _runThread(); void _endThread(); + bool _waitForFinish(PISystemTime max_tm); PIByteArray createThreadName(int size = 16) const; void setThreadName(); diff --git a/libs/main/thread/pithreadnotifier.cpp b/libs/main/thread/pithreadnotifier.cpp index b0a4a79e..46326988 100644 --- a/libs/main/thread/pithreadnotifier.cpp +++ b/libs/main/thread/pithreadnotifier.cpp @@ -115,6 +115,19 @@ void PIThreadNotifier::wait() { } +bool PIThreadNotifier::waitFor(PISystemTime timeout) { + bool ret = false; + m.lock(); + v.waitFor(m, timeout); + if (cnt > 0) { + cnt--; + ret = true; + } + m.unlock(); + return ret; +} + + //! \~\details //! \~english //! If many threads waiting, then notify randomly one.\n diff --git a/libs/main/thread/pithreadnotifier.h b/libs/main/thread/pithreadnotifier.h index e7657113..3e57232b 100644 --- a/libs/main/thread/pithreadnotifier.h +++ b/libs/main/thread/pithreadnotifier.h @@ -37,6 +37,11 @@ public: //! \~russian Начать ожидание, продолжает когда другой поток вызовет \a notify() void wait(); + //! \~english Start waiting no longer than "timeout", return \b true if other thread call \a notify(), \b false if timeout expired + //! \~russian Начать ожидание не дольше чем "timeout", возвращает \b true когда другой поток вызовал \a notify(), \b false если таймаут + //! истек + bool waitFor(PISystemTime timeout); + //! \~english Notify one waiting thread, which waiting on \a wait() function //! \~russian Уведомить один из ожидающих потоков, которые висят на методе \a wait() void notify();