From 9deae168a619d12cd705591fc0d10670cafc2413 Mon Sep 17 00:00:00 2001 From: peri4 Date: Thu, 21 Apr 2022 22:26:49 +0300 Subject: [PATCH] thread doc ru --- libs/main/thread/pimutex.cpp | 45 ++- libs/main/thread/pimutex.h | 4 +- libs/main/thread/pispinlock.cpp | 34 ++- libs/main/thread/pispinlock.h | 15 +- libs/main/thread/pithread.cpp | 395 ++++++++++++++++++++++++-- libs/main/thread/pithread.h | 57 +--- libs/main/thread/pithreadnotifier.cpp | 15 +- 7 files changed, 468 insertions(+), 97 deletions(-) diff --git a/libs/main/thread/pimutex.cpp b/libs/main/thread/pimutex.cpp index 7c75599c..54670e5e 100644 --- a/libs/main/thread/pimutex.cpp +++ b/libs/main/thread/pimutex.cpp @@ -31,13 +31,20 @@ //! \~russian \section PIMutex_sec0 Краткий обзор //! //! \~english -//! %PIMutex provides synchronization blocks between several threads. +//! %PIMutex provides critical code section defence between several threads. //! Using mutex guarantees execution of some code only one of threads. //! Mutex contains logic state and functions to change it: \a lock(), //! \a unlock() and \a tryLock(). //! -//! \~russian +//! For automatic lock-unlock use \a PIMutexLocker. //! +//! \~russian +//! %PIMutex предоставляет межпотоковую защиту критических секций кода. +//! Использование мьютекса гарантирует выполнение секции только один потоком. +//! Мьютекс состоит из логического состояния и методов для его изменения: +//! \a lock(), \a unlock() and \a tryLock(). +//! +//! Для автоматической блокировки-разблокировки используйте \a PIMutexLocker. //! //! \~english \section PIMutex_sec1 Usage //! \~russian \section PIMutex_sec1 Использование @@ -47,11 +54,15 @@ //! should to be started with \a lock() and finished with \a unlock(). //! //! \~russian +//! Части кода, которые должны быть выполнены только одним потоком в любой момент +//! времени должны начинаться с вызова \a lock() и заканчиваться вызовом \a unlock(). //! //! \~\code +//! // critical section start //! mutex.lock(); //! // ... your code here //! mutex.unlock(); +//! // critical section end //! \endcode //! \} @@ -68,14 +79,31 @@ //! \~\details //! //! \~english -//! When a PIMutexLocker object is created, it attempts to lock the mutex it is given, if "condition" true. -//! When control leaves the scope in which the PIMutexLocker object was created, -//! the PIMutexLocker is destructed and the mutex is released, if "condition" true. -//! If "condition" false this class do nothing. -//! The PIMutexLocker class is non-copyable. +//! When a %PIMutexLocker object is created, it attempts to lock the mutex it is given, if "condition" \c true. +//! When control leaves the scope in which the %PIMutexLocker object was created, +//! the %PIMutexLocker is destructed and the mutex is released, if "condition" was \c true. +//! +//! If "condition" \c false this class do nothing. +//! +//! The %PIMutexLocker class is non-copyable. //! //! \~russian +//! При создании экземпляра %PIMutexLocker блокируется переданный мьютекс, если "condition" \c true. +//! Когда выполнение покидает область жизни объекта, вызывается его деструктор и мьютекс +//! разблокируется, если "condition" был \c true. //! +//! Если "condition" \c false, то этот объект ничего не делает. +//! +//! Класс %PIMutexLocker некопируемый. +//! +//! \~\code +//! // critical section start +//! { +//! PIMutexLocker locker(mutex); +//! // ... your code here +//! } +//! // critical section end +//! \endcode //! \} @@ -118,6 +146,8 @@ PIMutex::~PIMutex() { //! If mutex is unlocked it set to locked state and returns immediate. //! If mutex is already locked function blocks until mutex will be unlocked //! \~russian +//! Если мьютекс свободен, то блокирует его и возвращает управление немедленно. +//! Если мьютекс заблокирован, то ожидает разблокировки, затем блокирует и возвращает управление void PIMutex::lock() { #if defined(WINDOWS) EnterCriticalSection(&(PRIVATE->mutex)); @@ -133,6 +163,7 @@ void PIMutex::lock() { //! \~english //! In any case this function returns immediate //! \~russian +//! В любом случае возвращает управление немедленно void PIMutex::unlock() { #if defined(WINDOWS) LeaveCriticalSection(&(PRIVATE->mutex)); diff --git a/libs/main/thread/pimutex.h b/libs/main/thread/pimutex.h index 3438da43..42665b0d 100644 --- a/libs/main/thread/pimutex.h +++ b/libs/main/thread/pimutex.h @@ -72,11 +72,11 @@ public: NO_COPY_CLASS(PIMutexLocker) //! \~english Constructs and lock "m" if "condition" is \c true - //! \~russian + //! \~russian Создает и блокирует мьютекс "m" если "condition" \c true PIMutexLocker(PIMutex & m, bool condition = true): mutex(m), cond(condition) {if (cond) mutex.lock();} //! \~english Unlock "m" if "condition" was \c true - //! \~russian + //! \~russian Разблокирует мьютекс "m" если "condition" был \c true ~PIMutexLocker() {if (cond) mutex.unlock();} private: diff --git a/libs/main/thread/pispinlock.cpp b/libs/main/thread/pispinlock.cpp index 57de73c8..16b61885 100644 --- a/libs/main/thread/pispinlock.cpp +++ b/libs/main/thread/pispinlock.cpp @@ -27,11 +27,18 @@ //! //! \~\details //! \~english -//! %PISpinlock provides synchronization blocks between several threads. -//! PISpinlock functionality similar to PIMutex, but working on atomic -//! type and \a lock() method wait with 100% CPU load. +//! %PISpinlock provides critical code section defence between several threads. +//! %PISpinlock functionality similar to PIMutex, but working on atomic +//! type and \a lock() method wait with 100% CPU core load. +//! +//! For automatic lock-unlock use \a PISpinlockLocker. //! //! \~russian +//! %PISpinlock предоставляет межпотоковую защиту критических секций кода. +//! Функционально он аналогичен PIMutex, однако работает на атомарном типе +//! и ожидание разблокировки в методе \a lock() нагружает ядро ЦП на 100%. +//! +//! Для автоматической блокировки-разблокировки используйте \a PISpinlockLocker. //! //! \~\note //! \~english @@ -39,6 +46,8 @@ //! important than CPU load! //! //! \~russian +//! Используйте этот класс вместо PIMutex когда время ожидания гораздо важнее +//! чем нагрузка на ЦП! //! //! \} @@ -49,17 +58,26 @@ //! //! \~\brief //! \~english %PISpinlock autolocker -//! \~russian +//! \~russian Автоблокировщик %PISpinlock //! //! //! \~\details //! \~english -//! When a PISpinlockLocker object is created, it attempts to lock the spinlock it is given, if "condition" true. -//! When control leaves the scope in which the PISpinlockLocker object was created, -//! the PISpinlockLocker is destructed and the spinlock is released, if "condition" true. +//! When a %PISpinlockLocker object is created, it attempts to lock the spinlock it is given, if "condition" true. +//! When control leaves the scope in which the %PISpinlockLocker object was created, +//! the %PISpinlockLocker is destructed and the spinlock is released, if "condition" true. +//! //! If "condition" false this class do nothing. -//! The PISpinlockLocker class is non-copyable. +//! +//! The %PISpinlockLocker class is non-copyable. //! //! \~russian +//! При создании экземпляра %PISpinlockLocker блокируется переданный спинлок, если "condition" \c true. +//! Когда выполнение покидает область жизни объекта, вызывается его деструктор и спинлок +//! разблокируется, если "condition" был \c true. +//! +//! Если "condition" \c false, то этот объект ничего не делает. +//! +//! Класс %PISpinlockLocker некопируемый. //! //! \} diff --git a/libs/main/thread/pispinlock.h b/libs/main/thread/pispinlock.h index 258dd202..5f1c64ff 100644 --- a/libs/main/thread/pispinlock.h +++ b/libs/main/thread/pispinlock.h @@ -36,29 +36,32 @@ public: NO_COPY_CLASS(PISpinlock) //! \~english Constructs unlocked spinlock - //! \~russian + //! \~russian Создает незаблокированный спинлок explicit PISpinlock() {flag.clear();} //! \~english Destroy spinlock - //! \~russian + //! \~russian Деструктор спинлока ~PISpinlock() {} //! \~english Lock spinlock - //! \~russian + //! \~russian Блокирует спинлок //! \~\details //! \~english //! If spinlock is unlocked it set to locked state and returns immediate. //! If spinlock is already locked function blocks until spinlock will be unlocked //! \~russian + //! Если спинлок свободен, то блокирует его и возвращает управление немедленно. + //! Если спинлок заблокирован, то ожидает разблокировки, затем блокирует и возвращает управление void lock() {while (flag.test_and_set(std::memory_order_acquire));} //! \~english Unlock spinlock - //! \~russian + //! \~russian Разблокирует спинлок //! \~\details //! \~english //! In any case this function returns immediate //! \~russian + //! В любом случае возвращает управление немедленно void unlock() {flag.clear(std::memory_order_release);} private: @@ -73,11 +76,11 @@ public: NO_COPY_CLASS(PISpinlockLocker) //! \~english Constructs and lock "s" if "condition" is \c true - //! \~russian + //! \~russianСоздает и блокирует спинлок "m" если "condition" \c true PISpinlockLocker(PISpinlock & s, bool condition = true): spinlock(s), cond(condition) {if (cond) spinlock.lock();} //! \~english Unlock "s" if "condition" was \c true - //! \~russian + //! \~russian Разблокирует спинлок "m" если "condition" был \c true ~PISpinlockLocker() {if (cond) spinlock.unlock();} private: diff --git a/libs/main/thread/pithread.cpp b/libs/main/thread/pithread.cpp index 0bba3e57..7cd87d95 100644 --- a/libs/main/thread/pithread.cpp +++ b/libs/main/thread/pithread.cpp @@ -72,30 +72,62 @@ __THREAD_FUNC_RET__ thread_function_once(void * t) {((PIThread*)t)->__thread_fun //! \~english \section PIThread_sec0 Synopsis //! \~russian \section PIThread_sec0 Краткий обзор //! \~english -//! Multithreading allow you to write program which will be executed +//! Multithreading allow you to execute code //! in several threads simultaneously. This trend allow you to use all //! cores of modern processors, but there are many dangers. //! //! This class provide virtual functions \a begin(), \a run() and \a end(), //! which describes start, execution and finish work of some process. //! These functions executes in \b separate thread. When you execute -//! \a start(), %PIThread create separate system thread and sequentially +//! \a start(int), %PIThread create separate system thread and sequentially //! executes function \a begin(), \a run() and \a end(). You can //! reimplement each function and write your own code to execute. +//! //! Scheme of functions executing: //! //! \~russian +//! Многопоточность позволяет исполнять код в нескольких потоках +//! одновременно и использовать все ядра современных процессоров. +//! Однако это таит в себе опасности. +//! +//! Этот класс предоставляет виртуальные методы \a begin(), \a run() и \a end(), +//! которые описывают старт, выполнение и завершение потоковой задачи. +//! Все эти методы исполняются в \b отдельном потоке. Когда выполняется +//! \a start(int), %PIThread создает отдельный поток средствами ОС и последовательно +//! выполняет \a begin(), \a run() и \a end(). Можно переопределить каждый метод +//! для реализации нужной задачи. +//! +//! Схема выполнения методов: //! //! \~\code{.cpp} -//! begin(); -//! event started(); -//! while (isRunning()) { -//! run(); -//! ThreadFunc(); -//! piMSleep(timer_delay); +//! virtual begin() +//! event started() +//! while (isRunning()) { // while not stop() +//! virtual run() +//! ThreadFunc() // Slot or lambda +//! piMSleep(timer_delay) // if timer_delay > 0 //! } -//! event stopped(); -//! end(); +//! event stopped() +//! virtual end() +//! \endcode +//! +//! \~english +//! If no internal loop needed, you can use \a startOnce() method instead of \a start(int). +//! +//! In this case scheme is next: +//! +//! \~russian +//! Если внутренний цикл не нужен, то можно использовать метод \a startOnce() вместо \a start(int). +//! +//! В этом случает схема выполнения следущая: +//! +//! \~\code{.cpp} +//! virtual begin() +//! event started() +//! virtual run() +//! ThreadFunc() // Slot or lambda +//! event stopped() +//! virtual end() //! \endcode //! //! \~english @@ -106,6 +138,67 @@ __THREAD_FUNC_RET__ thread_function_once(void * t) {((PIThread*)t)->__thread_fun //! and \a end() functions. //! //! \~russian +//! В отличии от прямого использования "pthread" или похожих механизмов +//! нет необходимости писать свой цикл внутри поточного метода и ожидать +//! в его теле. %PIThread уже рализует такой цикл, необходимо лишь +//! установить значение ожидания в конструкторе или при запуске потока, +//! и переопределить методы \a begin(), \a run() и \a end(). +//! +//! \~english Using with internal loop +//! \~russian Использование с внутренним циклом +//! \~\code{.cpp} +//! class MyThread: public PIThread { +//! PIOBJECT_SUBCLASS(MyThread, PIThread) +//! public: +//! void begin() override {piCout << "thread begin";} +//! void run() override {piCout << "thread run" << ++cnt;} +//! void end() override {piCout << "thread end";} +//! private: +//! int cnt = 0; +//! }; +//! +//! int main(int argc, char * argv[]) { +//! MyThread mt; +//! mt.start(100); +//! piMSleep(500); +//! mt.stop(true); +//! return 0; +//! } +//! +//! // thread begin +//! // thread run 1 +//! // thread run 2 +//! // thread run 3 +//! // thread run 4 +//! // thread run 5 +//! // thread end +//! \endcode +//! +//! \~english Using without internal loop +//! \~russian Использование без внутреннего цикла +//! \~\code{.cpp} +//! class MyThread: public PIThread { +//! PIOBJECT_SUBCLASS(MyThread, PIThread) +//! public: +//! void begin() override {piCout << "thread begin";} +//! void run() override {piCout << "thread run" << ++cnt;} +//! void end() override {piCout << "thread end";} +//! private: +//! int cnt = 0; +//! }; +//! +//! int main(int argc, char * argv[]) { +//! MyThread mt; +//! mt.startOnce(); +//! piMSleep(500); +//! mt.stop(true); +//! return 0; +//! } +//! +//! // thread begin +//! // thread run 1 +//! // thread end +//! \endcode //! //! //! \~english \section PIThread_sec1 Using without subclassing @@ -113,27 +206,243 @@ __THREAD_FUNC_RET__ thread_function_once(void * t) {((PIThread*)t)->__thread_fun //! \~english //! You can use %PIThread without subclassing by using "ThreadFunc" pointer //! that can be set from constructor or by overloaded function \a start(ThreadFunc func, int timer_delay). -//! If "func" if not null this function will be executed as \a run(). ThreadFunc is any static -//! function with format void func(void * data). "Data" is custom data set from constructor or -//! with function \a setData(). \n Also you can connect to event \a started(), but -//! in this case you should to white your thread main cycle, because this event raised only one time. +//! If "func" if not null this function will be executed after \a run(). +//! +//! ThreadFunc is any static function with format "void func(void * data)", or +//! lambda-function with format [...]( ){...}. +//! "Data" is custom data set from constructor or with \a setData() function. +//! +//! Also you can connect to event \a started(), but in this case you should to white +//! your thread main cycle, because this event raised only one time after thread start. //! //! \~russian +//! Возможно использовать %PIThread без наследования. Можно передать ему в конструкторе +//! или при запуске указатель на внешний метод "ThreadFunc". В основном цикле потока, +//! если "ThreadFunc" существует, он будет вызываться после \a run(). //! +//! ThreadFunc может быть любым статическим методом в формате "void func(void * data)", либо +//! лямбда-функцией в формате [...]( ){...}. +//! "Data" является произвольным указателем, задаваемым в конструкторе или методом \a setData(). +//! +//! Также можно присоединиться к событию \a started(), но в этом случае надо будет своими силами +//! реализовать весь цикл, т.к. это событие вызывается один раз после запуска потока. +//! +//! \~english Using with internal loop +//! \~russian Использование с внутренним циклом +//! \~\code{.cpp} +//! void myThreadFunc(void * d) { +//! int * cnt = (int*)d; +//! piCout << "thread run" << ++(*cnt); +//! } +//! +//! int main(int argc, char * argv[]) { +//! int cnt = 0; +//! PIThread mt; +//! mt.setData(&cnt); +//! mt.start(myThreadFunc, 100); +//! piMSleep(500); +//! mt.stop(true); +//! return 0; +//! } +//! +//! // thread run 1 +//! // thread run 2 +//! // thread run 3 +//! // thread run 4 +//! // thread run 5 +//! \endcode +//! +//! \~english Using without internal loop +//! \~russian Использование без внутреннего цикла +//! \~\code{.cpp} +//! void myThreadFunc(void * d) { +//! int * cnt = (int*)d; +//! piCout << "thread run" << ++(*cnt); +//! } +//! +//! int main(int argc, char * argv[]) { +//! int cnt = 0; +//! PIThread mt; +//! mt.setData(&cnt); +//! mt.startOnce(myThreadFunc); +//! piMSleep(500); +//! mt.stop(true); +//! return 0; +//! } +//! +//! // thread run 1 +//! \endcode +//! +//! \~english Using with lambda-function +//! \~russian Использование с лямбда-функцией +//! \~\code{.cpp} +//! int main(int argc, char * argv[]) { +//! int cnt = 0; +//! PIThread mt; +//! mt.start([&cnt](){ +//! piCout << "thread run" << ++cnt; +//! }, 100); +//! piMSleep(500); +//! mt.stop(true); +//! return 0; +//! } +//! +//! // thread run 1 +//! // thread run 2 +//! // thread run 3 +//! // thread run 4 +//! // thread run 5 +//! \endcode +//! +//! \~english Using with event +//! \~russian Использование с событием +//! \~\code{.cpp} +//! class MyObj: public PIObject { +//! PIOBJECT(MyObj) +//! public: +//! EVENT_HANDLER(void, threadRun) { +//! piForTimes (5) { +//! piCout << "threadRun" << ++cnt; +//! piMSleep(100); +//! } +//! }; +//! private: +//! int cnt = 0; +//! }; +//! +//! int main(int argc, char * argv[]) { +//! MyObj mo; +//! PIThread mt; +//! CONNECTU(&mt, started, &mo, threadRun); +//! mt.startOnce(); +//! mt.stop(true); +//! return 0; +//! } +//! +//! // threadRun 1 +//! // threadRun 2 +//! // threadRun 3 +//! // threadRun 4 +//! // threadRun 5 +//! \endcode //! //! \~english \section PIThread_sec2 Locking //! \~russian \section PIThread_sec2 Блокировки //! \~english //! %PIThread has inrternal mutex that can be locked and unlocked every \a run() if you set this flag -//! with function \a needLockRun(bool). Also you can access to this mutex by functions \a lock(), \a unlock() -//! and \a mutex(). Using this functions together with needLockRun(true) can guarantee one-thread access to -//! some data. +//! with function \a needLockRun(true). Also you can access to this mutex by functions \a lock(), \a unlock() +//! and \a mutex(). Using this functions outside of thread together with \a needLockRun(true) can defend +//! your data. //! //! \~russian +//! %PIThread имеет встроенный мьютекс, который может блокироваться и разблокироваться каждый \a run() +//! при установленном \a needLockRun(true). К нему есть доступ через методы \a lock(), \a unlock() и \a mutex(). +//! Использование этих методов вне потока совместно с \a needLockRun(true) поможет защитить данные. //! //! \} //! + +//! \fn bool PIThread::start(int timer_delay = -1) +//! \~\details +//! \~english +//! Start execution of \a run() in internal loop with +//! "timer_delay" delay in milliseconds. If "timer_delay" <= 0 +//! this is no delay in loop. Thread also exec external function +//! set by \a setSlot() if it`s not null. +//! \return \c false if thread already started or can`t start thread +//! +//! \~russian +//! Начинает выполнение \a run() во внутреннем цикле +//! с задержкой "timer_delay" миллисекунд. Если "timer_delay" <= 0 +//! то задержки не будет. Также поток вызывает внешний метод, +//! заданный через \a setSlot(), если он существует. +//! \return \c false если поток уже запущен или не может запуститься + + +//! \fn bool PIThread::startOnce() +//! \~\details +//! \~english +//! Start execution of \a run() once. Thread also exec +//! external function set by \a setSlot() if it`s not null. +//! \return \c false if thread already started or can`t start thread +//! +//! \~russian +//! Начинает выполнение \a run() один раз. Также поток вызывает +//! внешний метод, заданный через \a setSlot(), если он существует. +//! \return \c false если поток уже запущен или не может запуститься + + +//! \fn bool PIThread::startOnce(ThreadFunc func) +//! \~\details +//! \~english +//! Overloaded function. Set external function "func" before start. +//! \return \c false if thread already started or can`t start thread +//! +//! \~russian +//! Перегрузка метода, устанавливает внешний метод в "func" перед запуском. +//! \return \c false если поток уже запущен или не может запуститься + + +//! \fn void PIThread::stop(bool wait = false) +//! \~\details +//! \~english +//! Mark thread to stop execution and wait for finish +//! if "wait" is \c true. Thread can be stopped only outside of +//! \a run() or external method. +//! \warning This function can block for infinite +//! time if "wait" is \c true and any of thread function is +//! busy forever. +//! +//! \~russian +//! Помечает поток на остановку и ожидает завершения если +//! "wait" \c true. Поток может быть остановлен только вне +//! \a run() или внешнего метода. +//! \warning Этот метод может ожидать бесконечно если +//! "wait" \c true и любой из потоковых методов занят навечно. + + +//! \fn void PIThread::terminate() +//! \~\details +//! \~english +//! Stop execution of thread immediately. +//! \warning Memory can be corrupted, try not to use this method! +//! +//! \~russian +//! Немедленно останавливает поток. +//! \warning Это может повредить память, старайтесь не использовать этот метод! + + +//! \fn bool PIThread::waitForStart(int timeout_msecs = -1) +//! \~\details +//! \~english +//! Block until thread start within "timeout_msecs" +//! or forever if "timeout_msecs" < 0 +//! \return \c true if thread started less than timeout +//! \return \c false if timeout is exceeded +//! +//! \~russian +//! Блокирует до тех пор, пока поток не запустится в течении +//! "timeout_msecs", или бесконечно, если "timeout_msecs" < 0 +//! \return \c true если поток запустился менее чем за таймаут +//! \return \c false если таймаут истёк + + +//! \fn bool PIThread::waitForFinish(int timeout_msecs = -1) +//! \~\details +//! \~english +//! Block until thread finish for "timeout_msecs" +//! or forever if "timeout_msecs" < 0 +//! \return \c true if thread finished less than timeout +//! \return \c false if timeout is exceeded +//! +//! \~russian +//! Блокирует до тех пор, пока поток не завершится в течении +//! "timeout_msecs", или бесконечно, если "timeout_msecs" < 0 +//! \return \c true если поток завершился менее чем за таймаут +//! \return \c false если таймаут истёк + + #ifndef MICRO_PIP __PIThreadCollection *__PIThreadCollection::instance() { @@ -614,6 +923,36 @@ void PIThread::__thread_func_once__() { } +//! \~\details +//! \~english +//! This method create %PIThread with name "name" and execute +//! event handler "handler" of object "object" in this thread.\n +//! This %PIThread automatically delete on function finish. +//! +//! \~russian +//! Этот метод создает %PIThread с именем "name" и выполняет +//! обработчик "handler" объекта "object" в этом потоке.\n +//! %PIThread автоматически удаляется после завершения обработчика. +//! +//! \~\code +//! class MyObj: public PIObject { +//! PIOBJECT(MyObj) +//! public: +//! EVENT_HANDLER(void, threadRun) { +//! piForTimes (5) { +//! piCout << "threadRun"; +//! piMSleep(100); +//! } +//! }; +//! }; +//! +//! int main(int argc, char * argv[]) { +//! MyObj mo; +//! PIThread::runOnce(&mo, "threadRun"); +//! piMSleep(1000); // wait for thread finish +//! return 0; +//! } +//! \endcode void PIThread::runOnce(PIObject * object, const char * handler, const PIString & name) { PIThread * t = new PIThread(); t->setName(name); @@ -629,6 +968,28 @@ void PIThread::runOnce(PIObject * object, const char * handler, const PIString & } +//! \~\details +//! \~english +//! This method create %PIThread with name "name" and execute +//! lambda-function "func" in this thread.\n +//! This %PIThread automatically delete on function finish.\n +//! "func" shouldn`t have arguments. +//! +//! \~russian +//! Этот метод создает %PIThread с именем "name" и выполняет +//! лямбда-функцию "func" в этом потоке.\n +//! %PIThread автоматически удаляется после завершения функции.\n +//! "func" не должна иметь аргументов. +//! +//! \~\code +//! PIThread::runOnce([](){ +//! piForTimes(5) { +//! piCout << "thread func"; +//! piMSleep(100); +//! } +//! }); +//! piMSleep(1000); +//! \endcode void PIThread::runOnce(std::function func, const PIString & name) { PIThread * t = new PIThread(); t->setName(name); diff --git a/libs/main/thread/pithread.h b/libs/main/thread/pithread.h index 87554068..573e48ec 100644 --- a/libs/main/thread/pithread.h +++ b/libs/main/thread/pithread.h @@ -169,19 +169,12 @@ public: EVENT(started) EVENT(stopped) - //! \~english - //! Start event handler with name "handler" of object "object" - //! in separate thread with name "name" - //! and automatically delete it on function finish - //! - //! \~russian + //! \~english Call event handler "handler" of object "object" in separate thread + //! \~russian Вызывает обработчик "handler" объекта "object" в отдельном потоке static void runOnce(PIObject * object, const char * handler, const PIString & name = PIString()); - //! \~english - //! Start function "func" in separate thread with name "name" - //! and automatically delete it on function finish - //! - //! \~russian + //! \~english Call lambda-function "func" in separate thread + //! \~russian Вызывает лямбда-функцию "func" в отдельном потоке static void runOnce(std::function func, const PIString & name = PIString()); //! \handlers @@ -190,72 +183,30 @@ public: //! \fn bool start(int timer_delay = -1) //! \~english Start thread //! \~russian Запускает поток - //! \~\details - //! \~english - //! Start execution of \a run() in internal loop with - //! "timer_delay" delay in milliseconds. If "timer_delay" <= 0 - //! there is no delay in loop. Thread also exec external function - //! set by \a setSlot() if it`s not null - //! \return \c false if thread already started or can`t start thread - //! \~russian //! \fn bool startOnce() //! \~english Start thread without internal loop //! \~russian Запускает поток без внутреннего цикла - //! \~\details - //! \~english - //! Start execution of \a run() once. Thread also exec - //! external function set by \a setSlot() if it`s not null - //! \return \c false if thread already started or can`t start thread - //! \~russian //! \fn bool startOnce(ThreadFunc func) //! \~english Start thread without internal loop //! \~russian Запускает поток без внутреннего цикла - //! \~\details - //! \~english - //! Overloaded function. Set external function "func" before start - //! \return \c false if thread already started or can`t start thread - //! \~russian //! \fn void stop(bool wait = false) //! \~english Stop thread //! \~russian Останавливает поток - //! \~\details - //! \~english - //! Stop execution of thread and wait for it finish - //! if "wait" is \c true. This function can block for infinite - //! time if "wait" is \c true and any of thread function is - //! busy forever - //! \~russian //! \fn void terminate() //! \~english Strongly stop thread //! \~russian Жестко останавливает поток - //! \~\details - //! \~english - //! Stop execution of thread immediately - //! \~russian //! \fn bool waitForStart(int timeout_msecs = -1) //! \~english Wait for thread start //! \~russian Ожидает старта потока - //! \~\details - //! \~english - //! This function block until thread start for "timeout_msecs" - //! or forever if "timeout_msecs" < 0 - //! \return \c false if timeout is exceeded - //! \~russian //! \fn bool waitForFinish(int timeout_msecs = -1) //! \~english Wait for thread finish //! \~russian Ожидает завершения потока - //! \~\details - //! \~english - //! This function block until thread finish for "timeout_msecs" - //! or forever if "timeout_msecs" < 0 - //! \return \c false if timeout is exceeded - //! \~russian //! \fn void lock() //! \~english Lock internal mutex diff --git a/libs/main/thread/pithreadnotifier.cpp b/libs/main/thread/pithreadnotifier.cpp index 38f6e82b..8e04d15b 100644 --- a/libs/main/thread/pithreadnotifier.cpp +++ b/libs/main/thread/pithreadnotifier.cpp @@ -55,13 +55,18 @@ PIThreadNotifier::PIThreadNotifier() : cnt(0) {} //! \~\details //! \~english -//! If \a notifyOnce() has been called before, then returns immediately. +//! If \a notifyOnce() has been called before, then returns immediately.\n //! If \a notifyOnce() has been called "n" times, then returns immediately "n" times, -//! but only if wait in one thread. +//! but only if wait in one thread.\n //! If many threads waiting, then if \a notifyOnce() has been called "n" times, -//! all threads total returns "n" times in random sequence. +//! all threads total returns "n" times in undefined sequence. //! //! \~russian +//! Если ранее был вызван \a notifyOnce(), то возвращает управление немедленно.\n +//! Если ранее был вызван \a notifyOnce() "n" раз, то возвращает управление немедленно "n" раз, +//! но только если ожидать одним потоком.\n +//! Если ожидают несколько потоков, и \a notifyOnce() был вызван "n" раз, +//! то все потоки суммарно вернут управление "n" раз в неопределенной последовательности. //! void PIThreadNotifier::wait() { m.lock(); @@ -73,10 +78,12 @@ void PIThreadNotifier::wait() { //! \~\details //! \~english -//! If many threads waiting, then notify randomly one. +//! If many threads waiting, then notify randomly one.\n //! If call this "n" times, then notify any waiting threads totally "n" times. //! //! \~russian +//! Если ожидают несколько потоков, то уведомляет один случайный.\n +//! Если вызвать "n" раз, то все ожидающие потоки уведомятся суммарно "n" раз. void PIThreadNotifier::notifyOnce() { m.lock(); cnt++;