thread doc ru

This commit is contained in:
2022-04-21 22:26:49 +03:00
parent 93b881da1b
commit 9deae168a6
7 changed files with 468 additions and 97 deletions

View File

@@ -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<void ()> func, const PIString & name) {
PIThread * t = new PIThread();
t->setName(name);