This is a c++ asynchronous task object I wrote a while back that allows for executing tasks asynchronously, with a given task priority. Inheriting from the abstract CAsyncTask allows the user to define their own desired behavior for the task they need processed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
#pragma once #include <assert.h> #include <memory> #include <vector> namespace Chazix { class CFuncArg; class CAsyncTask; class CAsyncTaskPool; using FuncArgs = std::vector<std::unique_ptr<CFuncArg>>; using AsyncFunc = std::function<void(CAsyncTask&)>; using AsyncTask = std::shared_ptr<CAsyncTask>; //----------------------------------------------------------------------------------------------- enum class EAsyncTaskState { e_taskNone, e_taskInProgress, e_taskCompleted, e_taskFailed }; //----------------------------------------------------------------------------------------------- enum class EAsyncTaskPriority { e_low, e_med, e_high, e_count, }; //----------------------------------------------------------------------------------------------- struct SAsyncTaskPriorityInfo { SAsyncTaskPriorityInfo (EAsyncTaskPriority priority = EAsyncTaskPriority::e_high); SAsyncTaskPriorityInfo (EAsyncTaskPriority priority, unsigned id); EAsyncTaskPriority m_priority; unsigned m_taskId; }; //----------------------------------------------------------------------------------------------- // represents an argument to maintain within an asynchronous task class CFuncArg { public: CFuncArg (void* data, std::function<void (void*)> deleter) : m_data(data, deleter) { } void* GetData () { return m_data.get(); } private: // holds a void ptr, with custom deleter std::unique_ptr<void, std::function<void (void*)>> m_data; }; //----------------------------------------------------------------------------------------------- // task that executes asynchronously and then finishes in the main thread class CAsyncTask { public: CAsyncTask (); CAsyncTask ( FuncArgs& args, SAsyncTaskPriorityInfo& priorityInfo = SAsyncTaskPriorityInfo(), AsyncFunc onCompletion = nullptr, AsyncFunc onFailure = nullptr ); virtual ~CAsyncTask (); // how we know the task is completed virtual bool IsTaskCompleted () const; // retrieves this task's priority EAsyncTaskPriority GetPriority () const; // retrieves this task's id unsigned GetTaskId () const; // waits and blocks until this task is finished void Wait () const; // called from the main thread on task completion / failure void operator() (void); // retrieves reference to an argument at index location // it is up to the user to know what index holds what argument and type template <typename T> T& GetArgument (unsigned index) { assert(m_taskArgs.size() > index); return *reinterpret_cast<T*>((*m_taskArgs[index]).GetData()); } protected: // thread functions virtual void Process () = 0; // ----- // allow the CPoolTask to call Process friend class CPoolTask; protected: EAsyncTaskState m_taskState{EAsyncTaskState::e_taskNone}; EAsyncTaskPriority m_taskPriority{EAsyncTaskPriority::e_high}; unsigned m_taskid{0}; AsyncFunc m_onCompletion{nullptr}; AsyncFunc m_onFailure{nullptr}; FuncArgs m_taskArgs; // it's up the user to know what each argument in the vector represents }; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
#include "CAsyncTask.h" namespace Chazix { //----------------------------------------------------------------------------------------------- // SAsyncTaskPriorityInfo Implementation //----------------------------------------------------------------------------------------------- SAsyncTaskPriorityInfo::SAsyncTaskPriorityInfo (EAsyncTaskPriority priority) : m_priority(priority) { CAsyncTaskManager& taskManager = CAsyncTaskManager::GetInstance(); m_taskId = taskManager.GetNextTaskId(priority); } //----------------------------------------------------------------------------------------------- SAsyncTaskPriorityInfo::SAsyncTaskPriorityInfo (EAsyncTaskPriority priority, unsigned id) : m_priority(priority), m_taskId(id) { } //----------------------------------------------------------------------------------------------- // CAsyncTask Implementation //----------------------------------------------------------------------------------------------- CAsyncTask::CAsyncTask () : m_taskState(EAsyncTaskState::e_taskInProgress) { } //----------------------------------------------------------------------------------------------- CAsyncTask::CAsyncTask ( FuncArgs& args, SAsyncTaskPriorityInfo& priorityInfo, AsyncFunc onCompletion, AsyncFunc onFailure ) : m_taskState(EAsyncTaskState::e_taskInProgress), m_taskPriority(priorityInfo.m_priority), m_taskid(priorityInfo.m_taskId), m_onCompletion(onCompletion), m_onFailure(onFailure), m_taskArgs(std::move(args)) { } //----------------------------------------------------------------------------------------------- CAsyncTask::~CAsyncTask () { m_taskArgs.clear(); } //----------------------------------------------------------------------------------------------- bool CAsyncTask::IsTaskCompleted () const { return m_taskState != EAsyncTaskState::e_taskInProgress; } //----------------------------------------------------------------------------------------------- EAsyncTaskPriority CAsyncTask::GetPriority () const { return m_taskPriority; } //----------------------------------------------------------------------------------------------- unsigned CAsyncTask::GetTaskId () const { return m_taskid; } //----------------------------------------------------------------------------------------------- void CAsyncTask::Wait () const { while (!IsTaskCompleted()) { continue; } } //----------------------------------------------------------------------------------------------- void CAsyncTask::operator() (void) { switch (m_taskState) { case EAsyncTaskState::e_taskCompleted: if (m_onCompletion != nullptr) { m_onCompletion(*this); } break; case EAsyncTaskState::e_taskFailed: if (m_onFailure != nullptr) { m_onFailure(*this); } break; default: break; } } } |
The example bellow creates a timed asynchronous task, that is created and passed through to the CAsyncTaskManager for management and executed within a thread safe CAsyncTaskPool. I’ll provide these code samples at a later date.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
#include "CAsyncTask.h" using namespace Chazix; using namespace std::chrono; class CTimedAsyncTask : public CAsyncTask { public: CTimedAsyncTask ( FuncArgs& args, SAsyncTaskPriorityInfo& priorityInfo = SAsyncTaskPriorityInfo(), AsyncFunc onCompletion = nullptr, AsyncFunc onFailure = nullptr ) : CAsyncTask(args, priorityInfo, onCompletion, onFailure) { m_last = duration_cast<milliseconds>(system_clock::now().time_since_epoch()); } virtual void Process () override { unsigned& totalTime = GetArgument<unsigned>(1); milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch()); m_elapsed += ms - m_last; m_last = ms; if (m_elapsed.count() > totalTime) { m_taskState = EAsyncTaskState::e_taskCompleted; } } private: milliseconds m_last{0}; milliseconds m_elapsed{0}; }; static void ExecuteTimedAsyncTask (unsigned msTimeout) { CAsyncTaskManager& taskManager = CAsyncTaskManager::GetInstance(); FuncArgs args; taskManager.AddFuncArg(args, new std::string("ExecuteTimeAsyncTask")); taskManager.AddFuncArg(args, new unsigned(msTimeout)); taskManager.AddAsyncTask<CTimedAsyncTask>( taskManager.CreateAsyncTask<CTimedAsyncTask>( args, SAsyncTaskPriorityInfo(), [] (CAsyncTask& task)->void { std::cout << "Completed Task: " << task.GetArgument<std::string>(0).c_str() << std::endl; std::cout << " Timeout Requested: " << task.GetArgument<unsigned>(1) << std::endl; } ) ); } |