diff --git a/Toshi/Include/TKernel/TProfiler.h b/Toshi/Include/TKernel/TProfiler.h new file mode 100644 index 0000000..2139127 --- /dev/null +++ b/Toshi/Include/TKernel/TProfiler.h @@ -0,0 +1,22 @@ +#pragma once + +#include "TDebug.h" +#include + +TOSHI_NAMESPACE_BEGIN + +class TOSHI_EXPORT TProfiler +{ +public: + void Start(); + void Stop(); + + static void __stdcall PrintSummary(); + +private: + inline static TBOOL m_sProfilerStopped = TTRUE; + + LARGE_INTEGER m_iStartTime; +}; + +TOSHI_NAMESPACE_END \ No newline at end of file diff --git a/Toshi/Include/TKernel/TScheduler.h b/Toshi/Include/TKernel/TScheduler.h index fa2b743..d807413 100644 --- a/Toshi/Include/TKernel/TScheduler.h +++ b/Toshi/Include/TKernel/TScheduler.h @@ -1,14 +1,38 @@ #pragma once #include "TObject.h" +#include "TKernelInterface.h" +#include "TNodeTree.h" +#include "TTask.h" +#include "TProfiler.h" TOSHI_NAMESPACE_BEGIN +TBOOL Profiler_Control_ParentStart = TFALSE; +TBOOL Profiler_Control_ParentStop = TFALSE; +TProfiler Profiler_Program; + class TOSHI_EXPORT TScheduler : public TObject { DECLARE_DYNAMIC(TKernelInterface); public: + + TScheduler(); + void Update(); + void DestroyDyingTasks(TTask *a_pTask); +private: + void UpdateActiveTasks(TTask *a_pTask); + void DeleteTask(TTask *a_pTask); + void DeleteTaskRecurse(TTask *a_pTask); + void DeleteTaskAtomic(TTask *a_pTask); +private: + TKernelInterface *m_pKernel; // 0x8 + TNodeTree m_oTaskTree; // 0xC + TFLOAT m_fCurrentTimeDelta; // 0x24 + TFLOAT m_fTotalTime; // 0x28 + TFLOAT m_fDebugSlowTime; // 0x2C + TFLOAT m_iFrameCount; // 0x30 }; TOSHI_NAMESPACE_END \ No newline at end of file diff --git a/Toshi/Source/TKernel/TProfiler.cpp b/Toshi/Source/TKernel/TProfiler.cpp new file mode 100644 index 0000000..5b6221a --- /dev/null +++ b/Toshi/Source/TKernel/TProfiler.cpp @@ -0,0 +1,19 @@ +#include "TProfiler.h" + +TOSHI_NAMESPACE_USING + +void TProfiler::Start() +{ + m_sProfilerStopped = TFALSE; + QueryPerformanceCounter(&m_iStartTime); +} + +void TProfiler::Stop() +{ + m_sProfilerStopped = TTRUE; + +} + +void TProfiler::PrintSummary() +{ +} diff --git a/Toshi/Source/TKernel/TScheduler.cpp b/Toshi/Source/TKernel/TScheduler.cpp index b9ff93f..ab4fa91 100644 --- a/Toshi/Source/TKernel/TScheduler.cpp +++ b/Toshi/Source/TKernel/TScheduler.cpp @@ -4,6 +4,105 @@ TOSHI_NAMESPACE_USING IMPLEMENT_DYNAMIC(TScheduler, TObject); +TScheduler::TScheduler() +{ + m_pKernel = TNULL; + m_fCurrentTimeDelta = 0.0f; + m_fTotalTime = 0.0f; + m_fDebugSlowTime = 1.0f; + m_iFrameCount = 0; + TDPRINTF("Creating TScheduler.\n"); +} + void TScheduler::Update() { + if (Profiler_Control_ParentStart) { + Profiler_Program.Start(); + Profiler_Control_ParentStart = TFALSE; + } + if (Profiler_Control_ParentStop) { + Profiler_Program.Stop(); + TProfiler::PrintSummary(); + Profiler_Control_ParentStop = TFALSE; + } + TFLOAT deltaTime = m_pKernel->GetSystemTimer()->GetDelta(); + m_fTotalTime += deltaTime; + m_iFrameCount++; + + // Control delta time + if (deltaTime >= 0.0f) { + if (deltaTime >= m_fDebugSlowTime) { + m_fCurrentTimeDelta = m_fDebugSlowTime; + } + else { + m_fCurrentTimeDelta = deltaTime; + } + } + else { + m_fCurrentTimeDelta = 0.0f; + } + + DestroyDyingTasks(m_oTaskTree.AttachedToRoot()); + UpdateActiveTasks(m_oTaskTree.AttachedToRoot()); +} + +void TScheduler::DestroyDyingTasks(TTask* a_pTask) +{ + if (!a_pTask) return; + for (TTask* pTask = a_pTask->Prev(); pTask != TNULL; pTask = (pTask->Prev() != a_pTask) ? a_pTask->Prev() : TNULL) { + if (!pTask->IsDying()) { + if (pTask->Attached() != TNULL) { + DestroyDyingTasks(pTask->Attached()); + } + } + else { + DeleteTask(pTask); + } + } +} + +void TScheduler::UpdateActiveTasks(TTask* a_pTask) +{ +} + +void TScheduler::DeleteTask(TTask* a_pTask) +{ + DeleteTaskRecurse(a_pTask->Attached()); + DeleteTaskAtomic(a_pTask); +} + +void TScheduler::DeleteTaskRecurse(TTask* a_pTask) +{ + if (!a_pTask) return; + for (TTask* pTask = a_pTask->Prev(); pTask != TNULL; pTask = (pTask->Prev() != a_pTask) ? a_pTask->Prev() : TNULL) { + DeleteTaskAtomic(pTask); + } +} + +void TScheduler::DeleteTaskAtomic(TTask* a_pTask) +{ + if (!a_pTask) return; + TTask* taskParent = TNULL; + + if (a_pTask->IsChildOfDefaultRoot() == TFALSE) { + taskParent = a_pTask->Parent(); + + if (taskParent->IsDying() == TFALSE && taskParent->OnChildDying(a_pTask) == TFALSE) { + // The parent is not dying and doesn't allow us to kill the task + return; + } + } + + if (a_pTask->Attached() != TNULL) { + DeleteTaskRecurse(a_pTask->Attached()); + } + + TClass* pClass = &a_pTask->GetClass(); + a_pTask->OnDestroy(); + m_oTaskTree.Remove(a_pTask, TFALSE); + a_pTask->Delete(); + + if (taskParent != TNULL) { + taskParent->OnChildDied(pClass, a_pTask); + } }