Files
pip/libs/main/thread/pithread.h
2025-01-17 11:49:24 +03:00

309 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*! \file pithread.h
* \ingroup Thread
* \~\brief
* \~english Thread class
* \~russian Класс потока
*/
/*
PIP - Platform Independent Primitives
Thread
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PITHREAD_H
#define PITHREAD_H
#include "piinit.h"
#include "pimutex.h"
#include "piobject.h"
#include "pithreadnotifier.h"
class PIThread;
#ifndef MICRO_PIP
class PIIntrospectionThreads;
class PIP_EXPORT __PIThreadCollection: public PIObject {
PIOBJECT(__PIThreadCollection)
public:
static __PIThreadCollection * instance();
void registerThread(PIThread * t);
void unregisterThread(PIThread * t);
PIVector<PIThread *> threads() const;
void lock() { mutex.lock(); }
void unlock() { mutex.unlock(); }
void startedAuto(PIThread * t);
EVENT_HANDLER(void, stoppedAuto);
private:
PIVector<PIThread *> threads_, auto_threads_;
mutable PIMutex mutex, auto_mutex;
};
class PIP_EXPORT __PIThreadCollection_Initializer__ {
public:
__PIThreadCollection_Initializer__();
~__PIThreadCollection_Initializer__();
static int count_;
static __PIThreadCollection * __instance__;
};
static __PIThreadCollection_Initializer__ __PIThreadCollection_initializer__;
#endif // MICRO_PIP
typedef std::function<void(void *)> ThreadFunc;
class PIP_EXPORT PIThread: public PIObject {
PIOBJECT_SUBCLASS(PIThread, PIObject);
#ifndef MICRO_PIP
friend class PIIntrospectionThreads;
#endif
public:
NO_COPY_CLASS(PIThread);
//! \~english Contructs thread with custom data "data", external function "func" and main loop delay "loop_delay"
//! \~russian Создает поток с данными "data", функцией "func" и задержкой цикла "loop_delay"
PIThread(void * data, ThreadFunc func, bool startNow = false, PISystemTime loop_delay = {});
//! \~english Contructs thread with external function "func" and main loop delay "loop_delay"
//! \~russian Создает поток с функцией "func" и задержкой цикла "loop_delay"
PIThread(std::function<void()> func, bool startNow = false, PISystemTime loop_delay = {});
//! \~english Contructs thread with main loop delay "loop_delay"
//! \~russian Создает поток с задержкой цикла "loop_delay"
PIThread(bool startNow = false, PISystemTime loop_delay = {});
virtual ~PIThread();
//! \~english Priority of thread
//! \~russian Приоритет потока
enum Priority {
piLowerst /** \~english Lowest \~russian Низший */,
piLow /** \~english Low \~russian Низкий */,
piNormal /** \~english Normal, this is default priority of threads and timers \~russian Нормальный, это приоритет по умолчанию для
потоков и таймеров */
,
piHigh /** \~english High \~russian Высокий */,
piHighest /** \~english Highest \~russian Высший */
};
//! \~english Start thread
//! \~russian Запускает поток
bool start();
//! \~english Start thread
//! \~russian Запускает поток
bool start(PISystemTime loop_delay);
//! \~english Start thread
//! \~russian Запускает поток
bool start(ThreadFunc func);
//! \~english Start thread
//! \~russian Запускает поток
bool start(ThreadFunc func, PISystemTime loop_delay);
//! \~english Start thread
//! \~russian Запускает поток
bool start(std::function<void()> func);
//! \~english Start thread
//! \~russian Запускает поток
bool start(std::function<void()> func, PISystemTime loop_delay);
//! \~english Start thread without internal loop
//! \~russian Запускает поток без внутреннего цикла
bool startOnce();
//! \~english Start thread without internal loop
//! \~russian Запускает поток без внутреннего цикла
bool startOnce(ThreadFunc func);
//! \~english Start thread without internal loop
//! \~russian Запускает поток без внутреннего цикла
bool startOnce(std::function<void()> func);
EVENT_HANDLER0(void, stop);
EVENT_HANDLER0(void, terminate);
bool stopAndWait(int timeout_ms) DEPRECATEDM("use stopAndWait(PISystemTime)") {
return stopAndWait(PISystemTime::fromMilliseconds(timeout_ms));
}
//! \~english Stop thread and wait for finish. Returns \b false if timeout expired.
//! \~russian Останавливает поток и ожидает завершения. Возвращает \b false если таймаут истек.
bool stopAndWait(PISystemTime timeout = {});
//! \~english Set common data passed to external function
//! \~russian Устанавливает данные, передаваемые в функцию потока
void setData(void * d) { data_ = d; }
//! \~english Set external function that will be executed after every \a run()
//! \~russian Устанавливает функцию потока, вызываемую после каждого \a run()
void setSlot(ThreadFunc func) { ret_func = func; }
//! \~english Set external function that will be executed after every \a run()
//! \~russian Устанавливает функцию потока, вызываемую после каждого \a run()
void setSlot(std::function<void()> func) {
ret_func = [func](void *) { func(); };
}
//! \~english Set thread priority
//! \~russian Устанавливает приоритет потока
void setPriority(PIThread::Priority prior);
//! \~english Returns common data passed to external function
//! \~russian Возвращает данные, передаваемые в функцию потока
void * data() const { return data_; }
//! \~english Return thread priority
//! \~russian Возвращает приоритет потока
PIThread::Priority priority() const { return priority_; }
//! \~english Return if thread is running
//! \~russian Возвращает исполняется ли поток
bool isRunning() const { return running_; }
//! \~english Return if thread is stopping
//! \~russian Возвращает останавливается ли поток
bool isStopping() const { return running_ && terminating; }
//! \~english Wait for thread start
//! \~russian Ожидает старта потока
bool waitForStart(PISystemTime timeout = {});
bool waitForStart(int timeout_msecs) DEPRECATEDM("use waitForStart(PISystemTime)") {
return waitForStart(PISystemTime::fromMilliseconds(timeout_msecs));
}
//! \~english Wait for thread finish. Returns \b false if timeout expired.
//! \~russian Ожидает завершения потока. Возвращает \b false если таймаут истек.
bool waitForFinish(PISystemTime timeout = {});
bool waitForFinish(int timeout_msecs) DEPRECATEDM("use waitForFinish(PISystemTime)") {
return waitForFinish(PISystemTime::fromMilliseconds(timeout_msecs));
}
//! \~english Set necessity of lock every \a run() with internal mutex
//! \~russian Устанавливает необходимость блокировки внутреннего мьютекса каждый \a run()
void needLockRun(bool need) { lockRun = need; }
EVENT_HANDLER0(void, lock) const { thread_mutex.lock(); }
EVENT_HANDLER0(void, unlock) const { thread_mutex.unlock(); }
//! \~english Returns internal mutex
//! \~russian Возвращает внутренний мьютекс
PIMutex & mutex() const { return thread_mutex; }
//! \~english Returns thread ID
//! \~russian Возвращает ID потока
llong tid() const { return tid_; }
void __thread_func__();
void __thread_func_once__();
EVENT(started);
EVENT(stopped);
//! \~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 Call [lambda expression](https://en.cppreference.com/w/cpp/language/lambda) "func" in separate thread
//! \~russian Вызывает [лямбда-выражение](https://ru.cppreference.com/w/cpp/language/lambda) "func" в отдельном потоке
static void runOnce(std::function<void()> func, const PIString & name = PIString());
//! \handlers
//! \{
//! \fn void stop()
//! \brief
//! \~english Stop thread
//! \~russian Останавливает поток
//! \fn void terminate()
//! \brief
//! \~english Strongly stop thread
//! \~russian Жёстко прерывает поток
//! \fn void lock()
//! \brief
//! \~english Lock internal mutex
//! \~russian Блокирует внутренний мьютекс
//! \fn void unlock()
//! \brief
//! \~english Unlock internal mutex
//! \~russian Разблокирует внутренний мьютекс
//! \}
//! \events
//! \{
//! \fn void started()
//! \brief
//! \~english Raise on thread start
//! \~russian Вызывается при старте потока
//! \fn void stopped()
//! \brief
//! \~english Raise on thread stop
//! \~russian Вызывается при завершении потока
//! \}
protected:
static int priority2System(PIThread::Priority p);
//! \~english Function executed once at the start of thread
//! \~russian Метод выполняется один раз при старте потока
virtual void begin() { ; }
//! \~english Function executed at every "loop_delay" msecs until thread was stopped
//! \~russian Метод выполняется каждые "loop_delay" миллисекунд
virtual void run() { ; }
//! \~english Function executed once at the end of thread
//! \~russian Метод выполняется один раз при остановке потока
virtual void end() { ; }
std::atomic_bool terminating, running_, lockRun;
PISystemTime delay_;
llong tid_ = -1;
void * data_ = nullptr;
mutable PIMutex thread_mutex;
PIThread::Priority priority_ = piNormal;
ThreadFunc ret_func = nullptr;
PIThreadNotifier state_notifier;
PRIVATE_DECLARATION(PIP_EXPORT)
private:
bool _startThread(void * func);
void _beginThread();
void _runThread();
void _endThread();
bool _waitForFinish(PISystemTime max_tm);
PIByteArray createThreadName(int size = 16) const;
void setThreadName();
};
#endif // PITHREAD_H