/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: Schedular.cpp Date: 2021-6-26 Author: Reece ***/ #include #include "Async.hpp" #include "Schedular.hpp" #include "AsyncApp.hpp" namespace Aurora::Async { struct SchedEntry { AuUInt64 ns; DispatchTarget_t target; AuSPtr runnable; }; static Threading::Threads::ThreadUnique_t gThread; static Threading::Primitives::RWLockUnique_t gSchedLock; static AuList gEntries; static void GetDispatchableTasks(AuList &pending) { Threading::LockGuardPtr lock(gSchedLock->AsReadable()); auto time = Time::CurrentClockNS(); for (auto itr = gEntries.begin(); itr != gEntries.end(); ) { if (itr->ns <= time) { pending.push_back(std::move(*itr)); itr = gEntries.erase(itr); } else { itr ++; } } } static void SchedThread() { AuUInt32 counter {}; AuList pending; auto thread = Threading::Threads::GetThread(); while (!thread->Exiting()) { Threading::SleepNs(1000000 / 2); AuList pending; GetDispatchableTasks(pending); for (auto &entry : pending) { static_cast(GetAsyncApp())->Run(entry.target, entry.runnable); DecRunningTasks(); } counter++; if ((counter % 4) == 0) { // TODO: noting this should be called from main; however, we only pump console for.now RuntimeSysPump(); } } } void InitSched() { gSchedLock = Threading::Primitives::RWLockUnique(); Threading::Threads::AbstractThreadVectors handler; handler.DoRun = [=](const Threading::Threads::IAuroraThread *thread) { SchedThread(); }; gThread = Threading::Threads::ThreadUnique(handler); gThread->Run(); } void ShutdownSched() { gThread.reset(); gSchedLock.reset(); } void Schedule(AuUInt64 ns, DispatchTarget_t target, AuSPtr runnable) { Threading::LockGuardPtr lock(gSchedLock->AsWritable()); IncRunningTasks(); gEntries.push_back({ns, target, runnable}); } }