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

151 lines
5.7 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 Исполнитель пула потоков
//!
//! \details
//! \~english Executes tasks in a pool of worker threads.
//! \~russian Выполняет задачи в пуле рабочих потоков.
/*
PIP - Platform Independent Primitives
Stephan Fomenko, Ivan Pelipenko
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 "piblockingqueue.h"
#include "piprotectedvariable.h"
#include "pithread.h"
//! \~\ingroup Thread
//! \~\brief
//! \~english Fixed-size pool of worker threads for fire-and-forget tasks.
//! \~russian Фиксированный пул рабочих потоков для задач без ожидания результата.
class PIP_EXPORT PIThreadPoolWorker {
public:
//! \~english Constructs executor with \a threads_count worker threads.
//! \~russian Создает исполнитель с \a threads_count рабочими потоками.
explicit PIThreadPoolWorker(int threads_count = -1);
//! \~english Stops worker threads and destroys executor resources.
//! \~russian Останавливает рабочие потоки и уничтожает ресурсы исполнителя.
virtual ~PIThreadPoolWorker();
enum class TaskStatus {
Unknown,
Enqueued,
InProgress,
Done
};
//! \~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 { return m_running; }
int64_t enqueueTask(std::function<void(int64_t)> func, PIObject * context = nullptr);
int64_t enqueueTask(std::function<void()> func, PIObject * context = nullptr) {
return enqueueTask([func](int64_t) { func(); }, context);
}
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); });
}
template<typename O>
int64_t enqueueTask(O * obj, void (O::*member_func)()) {
return enqueueTask([obj, member_func](int64_t) { (obj->*member_func)(); });
}
bool removeTask(int64_t id);
TaskStatus taskStatus(int64_t id) const;
// DEPRECATED
//! \~\brief
//! \~english Submits \a runnable for asynchronous execution by a worker thread.
//! \~russian Передает \a runnable на асинхронное выполнение рабочим потоком.
//! \details
//! \~english
//! This is a best-effort fire-and-forget call and does not report whether the task was accepted.
//! \After shutdown requests new tasks are ignored.
//! \~russian
//! Это вызов по принципу best-effort без ожидания результата и без сообщения о том, была ли задача принята.
//! \После запроса на завершение новые задачи игнорируются.
void execute(std::function<void()> runnable);
void shutdownNow() DEPRECATEDM("Use stopAndWait()") { stopAndWait(); }
void shutdown() DEPRECATEDM("Use stop()") { stop(); }
bool isShutdown() const DEPRECATEDM("Use !isRunning()") { return !isRunning(); }
bool awaitTermination(PISystemTime timeout) DEPRECATEDM("Use waitForFinish()") { return waitForFinish(timeout); }
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;
std::atomic_bool m_running = {false};
std::atomic_int64_t next_task_id = {0};
};
typedef PIThreadPoolWorker PIThreadPoolExecutor DEPRECATEDM("Use PIThreadPoolWorker");
#endif // PITHREADPOOLWORKER_H