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

298 lines
10 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);
EVENT_HANDLER0(void, terminate);
//! \~english Stop thread and wait for finish.
//! \~russian Останавливает поток и ожидает завершения.
void stopAndWait(int timeout_ms = -1);
//! \~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);
bool waitForStart(PISystemTime timeout);
EVENT_HANDLER0(bool, waitForFinish) { return waitForFinish(-1); }
EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs);
bool waitForFinish(PISystemTime timeout);
//! \~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 bool start(int timer_delay = -1)
//! \brief
//! \~english Start thread
//! \~russian Запускает поток
//! \fn bool startOnce()
//! \brief
//! \~english Start thread without internal loop
//! \~russian Запускает поток без внутреннего цикла
//! \fn bool startOnce(ThreadFunc func)
//! \brief
//! \~english Start thread without internal loop
//! \~russian Запускает поток без внутреннего цикла
//! \fn void stop()
//! \brief
//! \~english Stop thread
//! \~russian Останавливает поток
//! \fn void terminate()
//! \brief
//! \~english Strongly stop thread
//! \~russian Жёстко прерывает поток
//! \fn bool waitForStart(int timeout_msecs = -1)
//! \brief
//! \~english Wait for thread start
//! \~russian Ожидает старта потока
//! \fn bool waitForFinish(int timeout_msecs = -1)
//! \brief
//! \~english Wait for thread finish
//! \~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 "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