diff options
| author | Léo Lam <leo@leolam.fr> | 2020-09-15 19:13:52 +0200 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2020-09-16 17:49:37 +0200 |
| commit | 3db6228dfc65a25da49bab26ab8bcf4abc69a98f (patch) | |
| tree | 3946a9211c2adc7213b1ae94ccf4baca22b73020 /src/KingSystem/Utils/Thread/TaskMgr.h | |
| parent | 8b7369dffb1e816b2f27ab0133d2bac218383a45 (diff) | |
ksys: Add more task utilities
* TaskMgr, ManagedTask, ManagedTaskHandle
* GameTaskThread: partial implementation because PhysicsMemSys / Havok
stuff hasn't been decompiled yet and calc_() requires PhysicsMemSys
Diffstat (limited to 'src/KingSystem/Utils/Thread/TaskMgr.h')
| -rw-r--r-- | src/KingSystem/Utils/Thread/TaskMgr.h | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/KingSystem/Utils/Thread/TaskMgr.h b/src/KingSystem/Utils/Thread/TaskMgr.h new file mode 100644 index 00000000..76a91ad9 --- /dev/null +++ b/src/KingSystem/Utils/Thread/TaskMgr.h @@ -0,0 +1,88 @@ +#pragma once + +#include <container/seadBuffer.h> +#include <container/seadOffsetList.h> +#include <container/seadSafeArray.h> +#include <heap/seadDisposer.h> +#include <prim/seadDelegate.h> +#include <prim/seadRuntimeTypeInfo.h> +#include <prim/seadScopedLock.h> +#include <prim/seadTypedBitFlag.h> +#include <thread/seadCriticalSection.h> +#include "KingSystem/Utils/Thread/Event.h" +#include "KingSystem/Utils/Types.h" + +namespace ksys::util { + +class ManagedTask; +class ManagedTaskHandle; +class TaskRequest; +struct TaskMgrRequest; + +using ManagedTaskFactory = sead::IDelegate1<ManagedTask**>; + +struct TaskMgrRequest { + /// Optional. If null, a task from the internal buffer will be used. + ManagedTask* task; + /// Must not be null. + TaskRequest* request; + /// Optional. + ManagedTaskHandle* handle; +}; +KSYS_CHECK_SIZE_NX150(TaskMgrRequest, 0x18); + +class TaskMgr { + SEAD_RTTI_BASE(TaskMgr) +public: + explicit TaskMgr(sead::Heap* heap); + virtual ~TaskMgr(); + + void init(s32 num_tasks, sead::Heap* heap, ManagedTaskFactory& factory); + void finalize(); + + void submitRequest(TaskMgrRequest& request); + bool trySubmitRequest(TaskMgrRequest& request); + + bool hasTasks() const; + + void freeTask(ManagedTask* task); + +protected: + enum class Flag { + HeapIsFreeable = 0x1, + }; + + bool fetchIdleTaskForRequest_(TaskMgrRequest& request, bool retry_until_success); + ManagedTask* fetchIdleTask_(bool retry_until_success); + + u8 getListIndex_() const { return mListIndex; } + u8 getListIndex2_() const { return ~mListIndex & 1; } + + void swapLists_() { + auto lock = sead::makeScopedLock(mCS2); + mListIndex = getListIndex2_(); + mNewFreeTaskEvent.resetSignal(); + } + + bool tryFetchTaskForRequest_(TaskMgrRequest& request, bool b) { + if (!mTasksCS.tryLock()) + return false; + + const bool ret = fetchIdleTaskForRequest_(request, b); + mTasksCS.unlock(); + return ret; + } + + sead::TypedBitFlag<Flag, u8> mFlags; + u8 mListIndex = 0; + ManagedTask* mTask = nullptr; + sead::CriticalSection mTasksCS; + sead::CriticalSection mCS2; + Event mNewFreeTaskEvent; + Event mEvent2; + sead::SafeArray<sead::OffsetList<ManagedTask>, 2> mFreeTaskLists; + sead::Buffer<ManagedTask*> mTasks; +}; +KSYS_CHECK_SIZE_NX150(TaskMgr, 0x158); + +} // namespace ksys::util |
