14#ifndef AUTONOMYTHREAD_H
15#define AUTONOMYTHREAD_H
17#include "../util/IPS.hpp"
20#include "../../external/threadpool/include/BS_thread_pool.hpp"
23#include <condition_variable>
45 enum class AutonomyThreadState
66 m_bStopThreads =
false;
67 m_eThreadState = AutonomyThreadState::eStopped;
68 m_nMainThreadMaxIterationPerSecond = 0;
84 m_bStopThreads =
true;
86 m_eThreadState = AutonomyThreadState::eStopping;
91 m_thMainThread.pause();
92 m_thMainThread.
purge();
96 m_thMainThread.
wait();
98 m_eThreadState = AutonomyThreadState::eStopped;
120 m_bStopThreads =
true;
122 m_eThreadState = AutonomyThreadState::eStopping;
127 m_thMainThread.pause();
128 m_thMainThread.
purge();
134 m_eThreadState = AutonomyThreadState::eStarting;
136 m_vPoolReturns.clear();
138 m_bStopThreads =
false;
141 std::future<void> fuMainReturn = m_thMainThread.
submit_task([
this]() { this->
RunThread(m_bStopThreads); });
145 m_thMainThread.unpause();
148 std::unique_lock<std::mutex> lkStartLock(m_muThreadRunningConditionMutex);
149 m_cdThreadRunningCondition.wait(lkStartLock,
151 {
return this->m_eThreadState == AutonomyThreadState::eRunning || this->m_eThreadState == AutonomyThreadState::eStopping; });
167 m_bStopThreads =
true;
169 m_eThreadState = AutonomyThreadState::eStopping;
185 m_thMainThread.
wait();
188 m_eThreadState = AutonomyThreadState::eStopped;
264 void RunPool(
const unsigned int nNumTasksToQueue,
const unsigned int nNumThreads = 2,
const bool bForceStopCurrentThreads =
false)
273 m_thPool.
reset(nNumThreads);
278 m_vPoolReturns.clear();
281 else if (bForceStopCurrentThreads)
293 for (
unsigned int i = 0; i < nNumTasksToQueue; ++i)
300 this->PooledLinearCode();
336 void RunDetachedPool(
const unsigned int nNumTasksToQueue,
const unsigned int nNumThreads = 2,
const bool bForceStopCurrentThreads =
false)
345 m_thPool.
reset(nNumThreads);
350 m_vPoolReturns.clear();
353 else if (bForceStopCurrentThreads)
365 for (
unsigned int i = 0; i < nNumTasksToQueue; ++i)
372 this->PooledLinearCode();
403 template<
typename N,
typename F>
404 void ParallelizeLoop(
const int nNumThreads,
const N tTotalIterations, F&& tLoopFunction)
411 [&tLoopFunction](
const int nStart,
const int nEnd)
414 tLoopFunction(nStart, nEnd);
470 m_nMainThreadMaxIterationPerSecond = nMaxIterationsPerSecond;
508 std::vector<T> vResults;
511 for (std::future<T> fResult : m_vPoolReturns)
514 vResults.emplace_back(fResult.get());
518 m_vPoolReturns.clear();
534 return m_nMainThreadMaxIterationPerSecond;
544 std::vector<std::future<T>> m_vPoolReturns;
545 std::atomic_bool m_bStopThreads;
546 std::atomic<AutonomyThreadState> m_eThreadState;
547 std::mutex m_muThreadRunningConditionMutex;
548 std::condition_variable m_cdThreadRunningCondition;
549 int m_nMainThreadMaxIterationPerSecond;
556 virtual void ThreadedContinuousCode() = 0;
557 virtual T PooledLinearCode() = 0;
574 std::chrono::_V2::system_clock::time_point tmStartTime;
580 if (m_nMainThreadMaxIterationPerSecond > 0)
583 tmStartTime = std::chrono::high_resolution_clock::now();
587 this->ThreadedContinuousCode();
590 if (m_nMainThreadMaxIterationPerSecond > 0)
593 std::chrono::_V2::system_clock::time_point tmEndTime = std::chrono::high_resolution_clock::now();
595 std::chrono::microseconds tmElapsedTime = std::chrono::duration_cast<std::chrono::microseconds>(tmEndTime - tmStartTime);
597 if (tmElapsedTime.count() < (1.0 / m_nMainThreadMaxIterationPerSecond) * 1000000)
600 int nSleepTime = ((1.0 / m_nMainThreadMaxIterationPerSecond) * 1000000) - tmElapsedTime.count();
602 std::this_thread::sleep_for(std::chrono::microseconds(nSleepTime));
607 if (m_eThreadState != AutonomyThreadState::eRunning && m_eThreadState != AutonomyThreadState::eStopping)
610 m_eThreadState = AutonomyThreadState::eRunning;
612 m_cdThreadRunningCondition.notify_all();
620 m_cdThreadRunningCondition.notify_all();
Interface class used to easily multithread a child class.
Definition AutonomyThread.hpp:38
void Join()
Waits for thread to finish executing and then closes thread. This method will block the calling code ...
Definition AutonomyThread.hpp:180
void ParallelizeLoop(const int nNumThreads, const N tTotalIterations, F &&tLoopFunction)
Given a ref-qualified looping function and an arbitrary number of iterations, this method will divide...
Definition AutonomyThread.hpp:404
void RunPool(const unsigned int nNumTasksToQueue, const unsigned int nNumThreads=2, const bool bForceStopCurrentThreads=false)
When this method is called, it starts/adds tasks to a thread pool that runs nNumTasksToQueue copies o...
Definition AutonomyThread.hpp:264
int GetMainThreadMaxIPS() const
Accessor for the Main Thread Max I P S private member.
Definition AutonomyThread.hpp:531
void SetMainThreadIPSLimit(int nMaxIterationsPerSecond=0)
Mutator for the Main Thread Max I P S private member.
Definition AutonomyThread.hpp:467
AutonomyThread()
Construct a new Autonomy Thread object.
Definition AutonomyThread.hpp:63
int GetPoolNumOfThreads()
Accessor for the Pool Num Of Threads private member.
Definition AutonomyThread.hpp:481
std::vector< T > GetPoolResults()
Accessor for the Pool Results private member. The action of getting results will destroy and remove t...
Definition AutonomyThread.hpp:505
void RequestStop()
Signals threads to stop executing user code, terminate. DOES NOT JOIN. This method will not force the...
Definition AutonomyThread.hpp:164
bool Joinable() const
Check if the code within the thread and all pools created by it are finished executing and the thread...
Definition AutonomyThread.hpp:201
IPS & GetIPS()
Accessor for the Frame I P S private member.
Definition AutonomyThread.hpp:224
int GetPoolQueueLength()
Accessor for the Pool Queue Size private member.
Definition AutonomyThread.hpp:491
void ClearPoolQueue()
Clears any tasks waiting to be ran in the queue, tasks currently running will remain running.
Definition AutonomyThread.hpp:429
void Start()
When this method is called, it starts a new thread that runs the code within the ThreadedContinuousCo...
Definition AutonomyThread.hpp:117
void RunThread(std::atomic_bool &bStopThread)
This method is ran in a separate thread. It is a middleware between the class member thread and the u...
Definition AutonomyThread.hpp:571
virtual ~AutonomyThread()
Destroy the Autonomy Thread object. If the parent object or main thread is destroyed or exited while ...
Definition AutonomyThread.hpp:81
void RunDetachedPool(const unsigned int nNumTasksToQueue, const unsigned int nNumThreads=2, const bool bForceStopCurrentThreads=false)
When this method is called, it starts a thread pool full of threads that don't return std::futures (l...
Definition AutonomyThread.hpp:336
bool PoolJoinable() const
Check if the internal pool threads are done executing code and the queue is empty.
Definition AutonomyThread.hpp:451
void JoinPool()
Waits for pool to finish executing tasks. This method will block the calling code until thread is fin...
Definition AutonomyThread.hpp:439
AutonomyThreadState GetThreadState() const
Accessor for the Threads State private member.
Definition AutonomyThread.hpp:214
A fast, lightweight, and easy-to-use C++17 thread pool class.
Definition BS_thread_pool.hpp:289
void reset()
Reset the pool with the total number of hardware threads available, as reported by the implementation...
Definition BS_thread_pool.hpp:545
void wait()
Wait for tasks to be completed. Normally, this function waits for all tasks, both those that are curr...
Definition BS_thread_pool.hpp:761
size_t get_tasks_queued() const
Get the number of tasks currently waiting in the queue to be executed by the threads.
Definition BS_thread_pool.hpp:366
void purge()
Purge all the tasks waiting in the queue. Tasks that are currently running will not be affected,...
Definition BS_thread_pool.hpp:444
void detach_task(F &&task BS_THREAD_POOL_PRIORITY_INPUT)
Submit a function with no arguments and no return value into the task queue, with the specified prior...
Definition BS_thread_pool.hpp:459
void detach_blocks(const T first_index, const T index_after_last, F &&block, const size_t num_blocks=0 BS_THREAD_POOL_PRIORITY_INPUT)
Parallelize a loop by automatically splitting it into blocks and submitting each block separately to ...
Definition BS_thread_pool.hpp:480
std::future< R > submit_task(F &&task BS_THREAD_POOL_PRIORITY_INPUT)
Submit a function with no arguments into the task queue, with the specified priority....
Definition BS_thread_pool.hpp:605
size_t get_tasks_total() const
Get the total number of unfinished tasks: either still waiting in the queue, or running in a thread....
Definition BS_thread_pool.hpp:388
concurrency_t get_thread_count() const
Get the number of threads in the pool.
Definition BS_thread_pool.hpp:399
This util class provides an easy way to keep track of iterations per second for any body of code.
Definition IPS.hpp:30
void Tick()
This method is used to update the iterations per second counter and recalculate all of the IPS metric...
Definition IPS.hpp:138