#pragma once #include #include #include #include #include #include #include #include #include "DllDefines.h" /* * @link : https://www.cppstories.com/2019/12/threading-loopers-cpp17/ */ using Runnable = std::function; class UTILITYDLL CRunnerTask { // dispatch class public: using Runnable = std::function; class CDispatcher { friend class CRunnerTask; // Allow the looper to access the private constructor. public: // Yet to be defined method, which will post the runnable // into the looper-queue. bool post(CRunnerTask::Runnable&& aRunnable) { return mAssignedRunner.post(std::move(aRunnable)); } private: // construction, since we want the looper to expose it's dispatcher exclusively! CDispatcher(CRunnerTask& aLooper) : mAssignedRunner(aLooper) {} private: // Store a reference to the attached looper in order to // emplace tasks into the queue. CRunnerTask& mAssignedRunner; }; // ctor CRunnerTask(); // Copy denied, Move to be implemented ~CRunnerTask(); // To be called, once the runner should start looping. bool run(); void stop(); bool running() const; Runnable next(); std::shared_ptr getDispatcher() { return mDispatcher; } private: // Conditionally-infinite loop doing sth. iteratively void runFunc(); // Shared implementation of exiting the loop-function and joining // to the main thread. void abortAndJoin(); bool post(Runnable&& aRunnable); // attributes std::thread mThread; std::atomic_bool mRunning; std::atomic_bool mAbortRequested; // std::recursive_mutex mRunnablesMutex; std::queue mRunnables; std::shared_ptr mDispatcher; };