Files
pip/libs/main/thread/pithreadpoolworker.h
2026-03-25 10:59:32 +03:00

178 lines
7.9 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 pithreadpoolworker.h
//! \~\ingroup Thread
//! \brief
//! \~english Thread pool worker
//! \~russian Исполнитель пула потоков
/*
PIP - Platform Independent Primitives
Ivan Pelipenko, Stephan Fomenko
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 PITHREADPOOLWORKER_H
#define PITHREADPOOLWORKER_H
#include "piprotectedvariable.h"
#include "pithread.h"
//! \~\ingroup Thread
//! \~\brief
//! \~english Fixed-size pool of worker threads for generic-purpose tasks.
//! \~russian Фиксированный пул рабочих потоков для задач общего назначения.
class PIP_EXPORT PIThreadPoolWorker: public PIObject {
PIOBJECT(PIThreadPoolWorker)
public:
//! \~english Constructs executor with \a threads_count worker threads. If \a threads_count < 0 processor threads count used.
//! \~russian Создает исполнитель с \a threads_count рабочими потоками. Если \a threads_count < 0 используется количество потоков
//! процессора.
explicit PIThreadPoolWorker(int threads_count = -1);
//! \~english Destroy worker threads. Call \a stopAndWait() before.
//! \~russian Уничтожает рабочие потоки. Вызывайте перед этим \a stopAndWait().
virtual ~PIThreadPoolWorker();
//! \~english Task status.
//! \~russian Статус задачи.
enum class TaskStatus {
Unknown /** \~english ID <= 0 or not queued yet \~russian ID <= 0 или не поставлена в очередь */,
Enqueued /** \~english Wait for execution \~russian Ожидает выполнения */,
InProgress /** \~english In execution now \~russian В процессе выполнения */,
DoneOrCancelled /** \~english Done or cancelled \~russian Выполнена или отменена */
};
//! \~english Starts the threads.
//! \~russian Запускает потоки.
void start();
//! \~english Requests graceful threads shutdown.
//! \~russian Запрашивает корректное завершение потоков.
void stop();
//! \~english Requests stop and waits for threads completion. Returns \b false if the timeout expires.
//! \~russian Запрашивает остановку и ожидает завершения потоков. Возвращает \b false, если таймаут истек.
bool stopAndWait(PISystemTime timeout = {});
//! \~english Waits until the threads starts. Returns \b false if the timeout expires first.
//! \~russian Ожидает запуска потоков. Возвращает \b false, если таймаут истек раньше.
bool waitForStart(PISystemTime timeout = {});
//! \~english Waits for threads completion. Returns \b false if the timeout expires first.
//! \~russian Ожидает завершения потоков. Возвращает \b false, если таймаут истек раньше.
bool waitForFinish(PISystemTime timeout = {});
//! \~english Returns whether the threads are currently running.
//! \~russian Возвращает, выполняются ли потоки в данный момент.
bool isRunning() const;
//! \~english Waits for all tasks completion. Returns \b false if the timeout expires first.
//! \~russian Ожидает завершения всех задач. Возвращает \b false, если таймаут истек раньше.
bool waitForTasks(PISystemTime timeout = {});
//! \~english Waits for task with id \a id completion. Returns \b false if the timeout expires first.
//! \~russian Ожидает завершения задачи с id \a id. Возвращает \b false, если таймаут истек раньше.
bool waitForTask(int64_t id, PISystemTime timeout = {});
//! \~english Starts threads, wait for all tasks complete and threads stop.
//! \~russian Запускает потоки, ожидает завершения всех задач и остановки потоков.
void exec();
//! \~english Queue functor to execution. Pass task ID in functor. Returns task ID.
//! \~russian Запланировать функтор на выполнение. В функтор передастся ID задачи. Возвращает ID задачи.
int64_t enqueueTask(std::function<void(int64_t)> func, PIObject * context = nullptr);
//! \~english Queue functor to execution. Returns task ID.
//! \~russian Запланировать функтор на выполнение. Возвращает ID задачи.
int64_t enqueueTask(std::function<void()> func, PIObject * context = nullptr) {
return enqueueTask([func](int64_t) { func(); }, context);
}
//! \~english Queue class member method to execution. Pass task ID in method. Returns task ID.
//! \~russian Запланировать член-метод класса на выполнение. В метод передастся ID задачи. Возвращает ID задачи.
template<typename O>
int64_t enqueueTask(O * obj, void (O::*member_func)(int64_t)) {
return enqueueTask([obj, member_func](int64_t id) { (obj->*member_func)(id); },
PIObject::isPIObject(obj) ? dynamic_cast<PIObject *>(obj) : nullptr);
}
//! \~english Queue class member method to execution. Returns task ID.
//! \~russian Запланировать член-метод класса на выполнение. Возвращает ID задачи.
template<typename O>
int64_t enqueueTask(O * obj, void (O::*member_func)()) {
return enqueueTask([obj, member_func](int64_t) { (obj->*member_func)(); },
PIObject::isPIObject(obj) ? dynamic_cast<PIObject *>(obj) : nullptr);
}
//! \~english Remove task with id \a id from queue. Returns if task delete.
//! \~russian Удаляет задачу с id \a id из очереди. Возвращиает была ли задача удалена.
bool removeTask(int64_t id);
//! \~english Remove all queued tasks.
//! \~russian Удаляет все задачи из очереди.
void clearTasks();
//! \~english Returns task status with id \a id.
//! \~russian Возвращиает статус задачи с id \a id.
TaskStatus taskStatus(int64_t id) const;
//! \events
//! \{
//! \fn void taskStarted(int64_t id)
//! \brief
//! \~english Raised on start execution task with id \a id.
//! \~russian Вызывается при старте выполнения задачи с id \a id.
EVENT1(taskStarted, int64_t, id);
//! \fn void taskFinished(int64_t id)
//! \brief
//! \~english Raised on finish execution task with id \a id.
//! \~russian Вызывается при завершении выполнения задачи с id \a id.
EVENT1(taskFinished, int64_t, id);
//! \}
private:
struct Worker {
PIThread thread;
PIThreadNotifier notifier;
std::atomic_int64_t in_work = {-1};
};
struct Task {
bool isValid() const { return func != nullptr; }
PIObject * context = nullptr;
std::function<void(int64_t)> func = nullptr;
int64_t id = -1;
};
void threadFunc(Worker * w);
mutable PIVector<Worker *> workers;
mutable PIProtectedVariable<PIQueue<Task>> tasks_queue;
PISet<PIObject *> contexts;
std::atomic_int64_t next_task_id = {0};
};
#endif // PITHREADPOOLWORKER_H