Files
pip/libs/main/thread/pithread.h

317 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"
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, int loop_delay = -1);
//! \~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, int loop_delay = -1);
//! \~english Contructs thread with main loop delay "loop_delay"
//! \~russian Создает поток с задержкой цикла "loop_delay"
PIThread(bool startNow = false, int loop_delay = -1);
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 Высший */
};
EVENT_HANDLER0(bool, start) {return start(-1);}
EVENT_HANDLER1(bool, start, int, timer_delay);
bool start(ThreadFunc func) {return start(func, -1);}
bool start(ThreadFunc func, int timer_delay) {ret_func = func; return start(timer_delay);}
bool start(std::function<void()> func) {return start(func, -1);}
bool start(std::function<void()> func, int timer_delay) {ret_func = [func](void*){func();}; return start(timer_delay);}
EVENT_HANDLER0(bool, startOnce);
EVENT_HANDLER1(bool, startOnce, ThreadFunc, func) {ret_func = func; return startOnce();}
EVENT_HANDLER0(void, stop) {stop(false);}
EVENT_HANDLER1(void, stop, bool, wait);
EVENT_HANDLER0(void, terminate);
//! \~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;}
EVENT_HANDLER0(bool, waitForStart) {return waitForStart(-1);}
EVENT_HANDLER1(bool, waitForStart, int, timeout_msecs);
EVENT_HANDLER0(bool, waitForFinish) {return waitForFinish(-1);}
EVENT_HANDLER1(bool, waitForFinish, int, 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
//! Start event handler with name "handler" of object "object"
//! in separate thread with name "name"
//! and automatically delete it on function finish
//!
//! \~russian
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
static void runOnce(std::function<void()> func, const PIString & name = PIString());
//! \handlers
//! \{
//! \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
//! \~russian Блокирует внутренний мьютекс
//! \fn void unlock()
//! \~english Unlock internal mutex
//! \~russian Разблокирует внутренний мьютекс
//! \}
//! \events
//! \{
//! \fn void started()
//! \~english Raise on thread start
//! \~russian Вызывается при старте потока
//! \fn void stopped()
//! \~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 "timer_delay" msecs until thread was stopped
//! \~russian Метод выполняется каждые "timer_delay" миллисекунд
virtual void run() {;}
//! \~english Function executed once at the end of thread
//! \~russian Метод выполняется один раз при остановке потока
virtual void end() {;}
std::atomic_bool terminating, running_, lockRun;
int delay_, policy_;
llong tid_;
void * data_;
mutable PIMutex thread_mutex;
PITimeMeasurer tmf_, tms_, tmr_;
PIThread::Priority priority_;
ThreadFunc ret_func;
PRIVATE_DECLARATION(PIP_EXPORT)
private:
bool _startThread(void * func);
void _beginThread();
void _runThread();
void _endThread();
};
#endif // PITHREAD_H