mirror of https://github.com/zeldaret/botw.git
ksys: Add more task utilities
* TaskMgr, ManagedTask, ManagedTaskHandle * GameTaskThread: partial implementation because PhysicsMemSys / Havok stuff hasn't been decompiled yet and calc_() requires PhysicsMemSys
This commit is contained in:
parent
8b7369dffb
commit
3db6228dfc
|
@ -76,8 +76,16 @@ add_executable(uking
|
|||
|
||||
src/KingSystem/Utils/Thread/Event.cpp
|
||||
src/KingSystem/Utils/Thread/Event.h
|
||||
src/KingSystem/Utils/Thread/GameTaskThread.cpp
|
||||
src/KingSystem/Utils/Thread/GameTaskThread.h
|
||||
src/KingSystem/Utils/Thread/ManagedTask.cpp
|
||||
src/KingSystem/Utils/Thread/ManagedTask.h
|
||||
src/KingSystem/Utils/Thread/ManagedTaskHandle.cpp
|
||||
src/KingSystem/Utils/Thread/ManagedTaskHandle.h
|
||||
src/KingSystem/Utils/Thread/Task.cpp
|
||||
src/KingSystem/Utils/Thread/Task.h
|
||||
src/KingSystem/Utils/Thread/TaskMgr.cpp
|
||||
src/KingSystem/Utils/Thread/TaskMgr.h
|
||||
src/KingSystem/Utils/Thread/TaskQueueBase.cpp
|
||||
src/KingSystem/Utils/Thread/TaskQueueBase.h
|
||||
src/KingSystem/Utils/Thread/TaskQueue.cpp
|
||||
|
|
|
@ -86813,19 +86813,19 @@
|
|||
0x00000071010c2a1c,sub_71010C2A1C,24,
|
||||
0x00000071010c2a34,sub_71010C2A34,20,
|
||||
0x00000071010c2a48,j__ZdlPv_1198,4,
|
||||
0x00000071010c2a4c,Res1::ctor,32,
|
||||
0x00000071010c2a6c,Res1::dtor,128,
|
||||
0x00000071010c2aec,Res1::b,160,
|
||||
0x00000071010c2b8c,sub_71010C2B8C,108,
|
||||
0x00000071010c2bf8,Res1::dtorDelete,136,
|
||||
0x00000071010c2c80,Res1::a,16,
|
||||
0x00000071010c2c90,Res1::o,164,
|
||||
0x00000071010c2d34,sub_71010C2D34,248,
|
||||
0x00000071010c2e2c,Res1::field18andfieldCTrue_NotReady,32,
|
||||
0x00000071010c2e4c,sub_71010C2E4C,36,
|
||||
0x00000071010c2e70,sub_71010C2E70,96,
|
||||
0x00000071010c2ed0,sub_71010C2ED0,8,
|
||||
0x00000071010c2ed8,sub_71010C2ED8,12,
|
||||
0x00000071010c2a4c,Res1::ctor,32,_ZN4ksys4util17ManagedTaskHandleC1Ev
|
||||
0x00000071010c2a6c,Res1::dtor,128,_ZN4ksys4util17ManagedTaskHandleD1Ev
|
||||
0x00000071010c2aec,Res1::b,160,_ZN4ksys4util17ManagedTaskHandle19removeTaskFromQueueEv
|
||||
0x00000071010c2b8c,sub_71010C2B8C,108,_ZN4ksys4util17ManagedTaskHandle8finalizeEv
|
||||
0x00000071010c2bf8,Res1::dtorDelete,136,_ZN4ksys4util17ManagedTaskHandleD0Ev
|
||||
0x00000071010c2c80,Res1::a,16,_ZNK4ksys4util17ManagedTaskHandle7hasTaskEv
|
||||
0x00000071010c2c90,Res1::o,164,_ZN4ksys4util17ManagedTaskHandle4waitEv
|
||||
0x00000071010c2d34,sub_71010C2D34,248,_ZN4ksys4util17ManagedTaskHandle4waitERKN4sead8TickSpanE
|
||||
0x00000071010c2e2c,Res1::field18andfieldCTrue_NotReady,32,_ZNK4ksys4util17ManagedTaskHandle14isTaskAttachedEv
|
||||
0x00000071010c2e4c,sub_71010C2E4C,36,_ZNK4ksys4util17ManagedTaskHandle27didTaskCompleteSuccessfullyEv
|
||||
0x00000071010c2e70,sub_71010C2E70,96,_ZN4ksys4util17ManagedTaskHandle10attachTaskERKNS1_10SetTaskArgE
|
||||
0x00000071010c2ed0,sub_71010C2ED0,8,_ZN4ksys4util17ManagedTaskHandle9setStatusENS1_6StatusE
|
||||
0x00000071010c2ed8,sub_71010C2ED8,12,_ZN4ksys4util17ManagedTaskHandle12setIsSuccessEb
|
||||
0x00000071010c2ee4,sub_71010C2EE4,516,
|
||||
0x00000071010c30e8,sub_71010C30E8,44,
|
||||
0x00000071010c3114,ElementSpark::ctor,280,
|
||||
|
@ -90490,33 +90490,33 @@
|
|||
0x00000071011f7284,sub_71011F7284,92,_ZNK4ksys4util17TaskPostRunResult18getRuntimeTypeInfoEv
|
||||
0x00000071011f72e0,j__ZdlPv_1226,4,_ZN4ksys4util17TaskPostRunResultD0Ev
|
||||
0x00000071011f72e4,sub_71011F72E4,44,
|
||||
0x00000071011f7310,EventPlusStringDerived::ctor,60,
|
||||
0x00000071011f734c,sub_71011F734C,72,
|
||||
0x00000071011f7394,EventPlusStringDerived::dtor,72,
|
||||
0x00000071011f73dc,EventPlusStringDerived::dtorDelete,80,
|
||||
0x00000071011f742c,EventPlusStringDerived::a,16,
|
||||
0x00000071011f743c,EventPlusStringDerived::b,44,
|
||||
0x00000071011f7468,EventPlusStringDerived::null1,4,
|
||||
0x00000071011f746c,EventPlusStringDerived::c,100,
|
||||
0x00000071011f74d0,EventPlusStringDerived::d,12,
|
||||
0x00000071011f74dc,EventPlusStringDerived::e,88,
|
||||
0x00000071011f7534,EventPlusStringDerived::f,12,
|
||||
0x00000071011f7540,EventPlusStringDerived::null1_0,4,
|
||||
0x00000071011f7544,EventPlusStringDerived::null1_1,4,
|
||||
0x00000071011f7548,EventPlusStringDerived::null1_2,4,
|
||||
0x00000071011f754c,sub_71011F754C,8,
|
||||
0x00000071011f7554,EventPlusStringDerived::setWorkerThread,8,
|
||||
0x00000071011f755c,EventPlusStringDerived::z,84,
|
||||
0x00000071011f75b0,sub_71011F75B0,128,
|
||||
0x00000071011f7630,EventPlusStringDerived::rtti1,204,
|
||||
0x00000071011f76fc,EventPlusStringDerived::rtti2,92,
|
||||
0x00000071011f7758,ThreadDerived::ctor,68,
|
||||
0x00000071011f779c,ThreadDerived::dtor,28,
|
||||
0x00000071011f77b8,ThreadDerived::dtorDelete,60,
|
||||
0x00000071011f77f4,ThreadDerived::quit,52,
|
||||
0x00000071011f7310,EventPlusStringDerived::ctor,60,_ZN4ksys4util11ManagedTaskC1EPN4sead4HeapE
|
||||
0x00000071011f734c,sub_71011F734C,72,_ZN4ksys4util11ManagedTaskC1EN4sead9IDisposer14HeapNullOptionE
|
||||
0x00000071011f7394,EventPlusStringDerived::dtor,72,_ZN4ksys4util11ManagedTaskD1Ev
|
||||
0x00000071011f73dc,EventPlusStringDerived::dtorDelete,80,_ZN4ksys4util11ManagedTaskD0Ev
|
||||
0x00000071011f742c,EventPlusStringDerived::a,16,_ZN4ksys4util11ManagedTask8prepare_EPNS0_11TaskRequestE
|
||||
0x00000071011f743c,EventPlusStringDerived::b,44,_ZN4ksys4util11ManagedTask4run_Ev
|
||||
0x00000071011f7468,EventPlusStringDerived::null1,4,_ZN4ksys4util11ManagedTask14onRunFinished_Ev
|
||||
0x00000071011f746c,EventPlusStringDerived::c,100,_ZN4ksys4util11ManagedTask9onFinish_Ev
|
||||
0x00000071011f74d0,EventPlusStringDerived::d,12,_ZN4ksys4util11ManagedTask13onPostFinish_Ev
|
||||
0x00000071011f74dc,EventPlusStringDerived::e,88,_ZN4ksys4util11ManagedTask10preRemove_Ev
|
||||
0x00000071011f7534,EventPlusStringDerived::f,12,_ZN4ksys4util11ManagedTask11postRemove_Ev
|
||||
0x00000071011f7540,EventPlusStringDerived::null1_0,4,_ZN4ksys4util11ManagedTask6onRun_Ev
|
||||
0x00000071011f7544,EventPlusStringDerived::null1_1,4,_ZN4ksys4util11ManagedTask12prepareImpl_EPNS0_11TaskRequestE
|
||||
0x00000071011f7548,EventPlusStringDerived::null1_2,4,_ZN4ksys4util11ManagedTask14preRemoveImpl_Ev
|
||||
0x00000071011f754c,sub_71011F754C,8,_ZNK4ksys4util11ManagedTask6isIdleEv
|
||||
0x00000071011f7554,EventPlusStringDerived::setWorkerThread,8,_ZN4ksys4util11ManagedTask6setMgrEPNS0_7TaskMgrE
|
||||
0x00000071011f755c,EventPlusStringDerived::z,84,_ZN4ksys4util11ManagedTask12attachHandleEPNS0_17ManagedTaskHandleEPNS0_13TaskQueueBaseE
|
||||
0x00000071011f75b0,sub_71011F75B0,128,_ZN4ksys4util11ManagedTask12detachHandleEv?
|
||||
0x00000071011f7630,EventPlusStringDerived::rtti1,204,_ZNK4ksys4util11ManagedTask27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
|
||||
0x00000071011f76fc,EventPlusStringDerived::rtti2,92,_ZNK4ksys4util11ManagedTask18getRuntimeTypeInfoEv
|
||||
0x00000071011f7758,ThreadDerived::ctor,68,_ZN4ksys4util14GameTaskThreadC1ERKN4sead14SafeStringBaseIcEEPNS2_4HeapEiNS2_12MessageQueue9BlockTypeElii
|
||||
0x00000071011f779c,ThreadDerived::dtor,28,_ZN4ksys4util14GameTaskThreadD2Ev
|
||||
0x00000071011f77b8,ThreadDerived::dtorDelete,60,_ZN4ksys4util14GameTaskThreadD0Ev
|
||||
0x00000071011f77f4,ThreadDerived::quit,52,_ZN4ksys4util14GameTaskThread4quitEb
|
||||
0x00000071011f7828,ThreadDerived::calc_,164,
|
||||
0x00000071011f78cc,sub_71011F78CC,204,
|
||||
0x00000071011f7998,sub_71011F7998,92,
|
||||
0x00000071011f78cc,sub_71011F78CC,204,_ZNK4ksys4util14GameTaskThread27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
|
||||
0x00000071011f7998,sub_71011F7998,92,_ZNK4ksys4util14GameTaskThread18getRuntimeTypeInfoEv
|
||||
0x00000071011f79f4,sub_71011F79F4,140,
|
||||
0x00000071011f7a80,SetMainInvokerClass::ctor,20,_ZN4ksys4util18TaskDelegateSetterC1Ev
|
||||
0x00000071011f7a94,SetMainInvokerClass::dtor,4,_ZN4ksys4util18TaskDelegateSetterD1Ev
|
||||
|
@ -90569,19 +90569,19 @@
|
|||
0x00000071011f8748,sub_71011F8748,112,_ZNK4ksys4util18TaskPostRunContext27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
|
||||
0x00000071011f87b8,sub_71011F87B8,92,_ZNK4ksys4util18TaskPostRunContext18getRuntimeTypeInfoEv
|
||||
0x00000071011f8814,j__ZdlPv_1229,4,_ZN4ksys4util18TaskPostRunContextD0Ev
|
||||
0x00000071011f8818,WorkerThread::ctor,172,
|
||||
0x00000071011f88c4,WorkerThread::dtor,80,
|
||||
0x00000071011f8914,WorkerThread::deleteElements,196,
|
||||
0x00000071011f89d8,WorkerThread::dtorDelete,88,
|
||||
0x00000071011f8a30,WorkerThread::submitRequest,408,
|
||||
0x00000071011f8bc8,WorkerThread::lockAndRemoveSomethingFromQueueAndWait,276,
|
||||
0x00000071011f8cdc,sub_71011F8CDC,112,
|
||||
0x00000071011f8d4c,WorkerThread::submitRequest2,460,
|
||||
0x00000071011f8f18,WorkerThread::init,380,
|
||||
0x00000071011f9094,WorkerThread::hasQueue,16,
|
||||
0x00000071011f90a4,WorkerThread::removeSomethingFromQueueAndWait,428,
|
||||
0x00000071011f9250,WorkerThread::rtti1,112,
|
||||
0x00000071011f92c0,WorkerThread::rtti2,92,
|
||||
0x00000071011f8818,WorkerThread::ctor,172,_ZN4ksys4util7TaskMgrC1EPN4sead4HeapE
|
||||
0x00000071011f88c4,WorkerThread::dtor,80,_ZN4ksys4util7TaskMgrD1Ev
|
||||
0x00000071011f8914,WorkerThread::deleteElements,196,_ZN4ksys4util7TaskMgr8finalizeEv
|
||||
0x00000071011f89d8,WorkerThread::dtorDelete,88,_ZN4ksys4util7TaskMgrD0Ev
|
||||
0x00000071011f8a30,WorkerThread::submitRequest,408,_ZN4ksys4util7TaskMgr13submitRequestERNS0_14TaskMgrRequestE
|
||||
0x00000071011f8bc8,WorkerThread::lockAndRemoveSomethingFromQueueAndWait,276,_ZN4ksys4util7TaskMgr24fetchIdleTaskForRequest_ERNS0_14TaskMgrRequestEb?
|
||||
0x00000071011f8cdc,sub_71011F8CDC,112,_ZN4ksys4util7TaskMgr8freeTaskEPNS0_11ManagedTaskE
|
||||
0x00000071011f8d4c,WorkerThread::submitRequest2,460,_ZN4ksys4util7TaskMgr16trySubmitRequestERNS0_14TaskMgrRequestE
|
||||
0x00000071011f8f18,WorkerThread::init,380,_ZN4ksys4util7TaskMgr4initEiPN4sead4HeapERNS2_10IDelegate1IPPNS0_11ManagedTaskEEE?
|
||||
0x00000071011f9094,WorkerThread::hasQueue,16,_ZNK4ksys4util7TaskMgr8hasTasksEv
|
||||
0x00000071011f90a4,WorkerThread::removeSomethingFromQueueAndWait,428,_ZN4ksys4util7TaskMgr14fetchIdleTask_Eb
|
||||
0x00000071011f9250,WorkerThread::rtti1,112,_ZNK4ksys4util7TaskMgr27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
|
||||
0x00000071011f92c0,WorkerThread::rtti2,92,_ZNK4ksys4util7TaskMgr18getRuntimeTypeInfoEv
|
||||
0x00000071011f931c,SeadController::getInstance,12,
|
||||
0x00000071011f9328,SeadController::setInstance,12,
|
||||
0x00000071011f9334,sub_71011F9334,12,
|
||||
|
|
Can't render this file because it is too large.
|
|
@ -0,0 +1,15 @@
|
|||
#include "KingSystem/Utils/Thread/GameTaskThread.h"
|
||||
|
||||
namespace ksys::util {
|
||||
|
||||
GameTaskThread::GameTaskThread(const sead::SafeString& name, sead::Heap* heap, s32 priority,
|
||||
sead::MessageQueue::BlockType block_type, long quit_msg,
|
||||
s32 stack_size, s32 message_queue_size)
|
||||
: TaskThread(name, heap, priority, block_type, quit_msg, stack_size, message_queue_size) {}
|
||||
|
||||
void GameTaskThread::quit(bool) {
|
||||
mMessageQueue.push(cMessage_GameThreadQuit, sead::MessageQueue::BlockType::Blocking);
|
||||
Thread::quit(false);
|
||||
}
|
||||
|
||||
} // namespace ksys::util
|
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include "KingSystem/Utils/Thread/TaskThread.h"
|
||||
#include "KingSystem/Utils/Types.h"
|
||||
|
||||
namespace ksys::util {
|
||||
|
||||
class GameTaskThread : public TaskThread {
|
||||
SEAD_RTTI_OVERRIDE(GameTaskThread, TaskThread)
|
||||
public:
|
||||
GameTaskThread(const sead::SafeString& name, sead::Heap* heap, s32 priority,
|
||||
sead::MessageQueue::BlockType block_type, long quit_msg, s32 stack_size,
|
||||
s32 message_queue_size);
|
||||
~GameTaskThread() override { ; }
|
||||
|
||||
void quit(bool is_jam) override;
|
||||
|
||||
protected:
|
||||
static constexpr s32 cMessage_GameThreadQuit = 4;
|
||||
|
||||
void calc_(sead::MessageQueue::Element msg) override;
|
||||
u8 _1a0 = 0;
|
||||
s32 _1a4 = -1;
|
||||
};
|
||||
KSYS_CHECK_SIZE_NX150(GameTaskThread, 0x1a8);
|
||||
|
||||
} // namespace ksys::util
|
|
@ -0,0 +1,106 @@
|
|||
#include "KingSystem/Utils/Thread/ManagedTask.h"
|
||||
#include "KingSystem/Utils/Thread/ManagedTaskHandle.h"
|
||||
#include "KingSystem/Utils/Thread/TaskMgr.h"
|
||||
#include "KingSystem/Utils/Thread/TaskQueueLock.h"
|
||||
|
||||
namespace ksys::util {
|
||||
|
||||
ManagedTask::ManagedTask(sead::Heap* heap) : Task(heap) {}
|
||||
|
||||
ManagedTask::ManagedTask(sead::IDisposer::HeapNullOption heap_null_option)
|
||||
: Task(nullptr, heap_null_option) {}
|
||||
|
||||
ManagedTask::~ManagedTask() {
|
||||
if (mHandle) {
|
||||
mHandle->finalize();
|
||||
mHandle = nullptr;
|
||||
}
|
||||
finalize_();
|
||||
}
|
||||
|
||||
void ManagedTask::prepare_(TaskRequest* request) {
|
||||
mIsIdle = false;
|
||||
prepareImpl_(request);
|
||||
}
|
||||
|
||||
void ManagedTask::run_() {
|
||||
Task::run_();
|
||||
onRun_();
|
||||
}
|
||||
|
||||
void ManagedTask::onRunFinished_() {}
|
||||
|
||||
void ManagedTask::onFinish_() {
|
||||
if (auto* handle = mHandle) {
|
||||
handle->setIsSuccess(isSuccess());
|
||||
handle->setStatus(ManagedTaskHandle::Status::TaskFinished);
|
||||
}
|
||||
|
||||
if (!mHandle && mMgr)
|
||||
mMgr->freeTask(this);
|
||||
}
|
||||
|
||||
void ManagedTask::onPostFinish_() {
|
||||
mIsIdle = true;
|
||||
}
|
||||
|
||||
void ManagedTask::preRemove_() {
|
||||
preRemoveImpl_();
|
||||
|
||||
if (mHandle)
|
||||
mHandle->setStatus(ManagedTaskHandle::Status::TaskRemoved);
|
||||
|
||||
if (!mHandle && mMgr)
|
||||
mMgr->freeTask(this);
|
||||
}
|
||||
|
||||
void ManagedTask::postRemove_() {
|
||||
mIsIdle = true;
|
||||
}
|
||||
|
||||
void ManagedTask::onRun_() {}
|
||||
|
||||
void ManagedTask::prepareImpl_(TaskRequest*) {}
|
||||
|
||||
void ManagedTask::preRemoveImpl_() {}
|
||||
|
||||
bool ManagedTask::isIdle() const {
|
||||
return mIsIdle;
|
||||
}
|
||||
|
||||
void ManagedTask::setMgr(TaskMgr* mgr) {
|
||||
mMgr = mgr;
|
||||
}
|
||||
|
||||
void ManagedTask::attachHandle(ManagedTaskHandle* handle, TaskQueueBase* queue) {
|
||||
if (mHandle)
|
||||
return;
|
||||
|
||||
if (handle) {
|
||||
handle->attachTask({this, queue});
|
||||
handle->setStatus(ManagedTaskHandle::Status::TaskAttached);
|
||||
}
|
||||
mHandle = handle;
|
||||
}
|
||||
|
||||
// NON_MATCHING: switch
|
||||
void ManagedTask::detachHandle() {
|
||||
TaskQueueLock lock;
|
||||
lock.lock(mQueue);
|
||||
|
||||
if (mHandle) {
|
||||
switch (mHandle->getStatus()) {
|
||||
case ManagedTaskHandle::Status::TaskRemoved:
|
||||
case ManagedTaskHandle::Status::TaskFinished:
|
||||
mHandle = nullptr;
|
||||
if (mMgr)
|
||||
mMgr->freeTask(this);
|
||||
break;
|
||||
default:
|
||||
mHandle = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ksys::util
|
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include "KingSystem/Utils/Thread/Task.h"
|
||||
#include "KingSystem/Utils/Types.h"
|
||||
|
||||
namespace ksys::util {
|
||||
|
||||
class ManagedTaskHandle;
|
||||
class TaskMgr;
|
||||
|
||||
class ManagedTask : public Task {
|
||||
SEAD_RTTI_OVERRIDE(ManagedTask, Task)
|
||||
public:
|
||||
explicit ManagedTask(sead::Heap* heap);
|
||||
explicit ManagedTask(sead::IDisposer::HeapNullOption heap_null_option);
|
||||
~ManagedTask() override;
|
||||
|
||||
bool isIdle() const;
|
||||
|
||||
protected:
|
||||
friend class ManagedTaskHandle;
|
||||
friend class TaskMgr;
|
||||
|
||||
void setMgr(TaskMgr* mgr);
|
||||
void attachHandle(ManagedTaskHandle* handle, TaskQueueBase* queue);
|
||||
void detachHandle();
|
||||
|
||||
void prepare_(TaskRequest* request) override;
|
||||
void run_() override;
|
||||
void onRunFinished_() override;
|
||||
void onFinish_() override;
|
||||
void onPostFinish_() override;
|
||||
void preRemove_() override;
|
||||
void postRemove_() override;
|
||||
|
||||
virtual void onRun_();
|
||||
virtual void prepareImpl_(TaskRequest* req);
|
||||
virtual void preRemoveImpl_();
|
||||
|
||||
bool mIsIdle = true;
|
||||
TaskMgr* mMgr = nullptr;
|
||||
// FIXME: rename
|
||||
ManagedTaskHandle* mHandle = nullptr;
|
||||
};
|
||||
KSYS_CHECK_SIZE_NX150(ManagedTask, 0xc0);
|
||||
|
||||
} // namespace ksys::util
|
|
@ -0,0 +1,107 @@
|
|||
#include "KingSystem/Utils/Thread/ManagedTaskHandle.h"
|
||||
#include "KingSystem/Utils/Thread/ManagedTask.h"
|
||||
#include "KingSystem/Utils/Thread/TaskQueueBase.h"
|
||||
#include "KingSystem/Utils/Thread/TaskQueueLock.h"
|
||||
|
||||
namespace ksys::util {
|
||||
|
||||
ManagedTaskHandle::ManagedTaskHandle() = default;
|
||||
|
||||
ManagedTaskHandle::~ManagedTaskHandle() {
|
||||
removeTaskFromQueue();
|
||||
finalize();
|
||||
}
|
||||
|
||||
void ManagedTaskHandle::removeTaskFromQueue() {
|
||||
if (!mQueue)
|
||||
return;
|
||||
|
||||
incrementRef_();
|
||||
|
||||
if (mTask)
|
||||
mTask->removeFromQueue();
|
||||
|
||||
decrementRef_();
|
||||
}
|
||||
|
||||
void ManagedTaskHandle::finalize() {
|
||||
if (mQueue)
|
||||
decrementRef_();
|
||||
}
|
||||
|
||||
bool ManagedTaskHandle::hasTask() const {
|
||||
return mTask != nullptr;
|
||||
}
|
||||
|
||||
bool ManagedTaskHandle::wait() {
|
||||
if (!mQueue)
|
||||
return true;
|
||||
|
||||
incrementRef_();
|
||||
|
||||
if (mTask)
|
||||
mTask->wait();
|
||||
|
||||
decrementRef_();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ManagedTaskHandle::wait(const sead::TickSpan& wait_duration) {
|
||||
if (!mQueue)
|
||||
return true;
|
||||
|
||||
incrementRef_();
|
||||
|
||||
if (!mTask) {
|
||||
decrementRef_();
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool ret = mTask->wait(wait_duration);
|
||||
decrementRef_();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ManagedTaskHandle::isTaskAttached() const {
|
||||
return mTask && mStatus == Status::TaskAttached;
|
||||
}
|
||||
|
||||
bool ManagedTaskHandle::didTaskCompleteSuccessfully() const {
|
||||
return mStatus == Status::TaskFinished && mSuccess;
|
||||
}
|
||||
|
||||
bool ManagedTaskHandle::attachTask(const SetTaskArg& arg) {
|
||||
mTask = arg.task;
|
||||
mQueue = arg.queue;
|
||||
incrementRef_();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ManagedTaskHandle::setStatus(Status status) {
|
||||
mStatus = status;
|
||||
}
|
||||
|
||||
void ManagedTaskHandle::setIsSuccess(bool success) {
|
||||
mSuccess = success;
|
||||
}
|
||||
|
||||
inline void ManagedTaskHandle::incrementRef_() {
|
||||
TaskQueueLock lock;
|
||||
mQueue->lock(&lock);
|
||||
++mRefCount;
|
||||
}
|
||||
|
||||
inline void ManagedTaskHandle::decrementRef_() {
|
||||
TaskQueueLock lock;
|
||||
mQueue->lock(&lock);
|
||||
|
||||
if (mRefCount > 0)
|
||||
--mRefCount;
|
||||
|
||||
if (mRefCount <= 0 && mTask) {
|
||||
mTask->detachHandle();
|
||||
mTask = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ksys::util
|
|
@ -0,0 +1,60 @@
|
|||
#pragma once
|
||||
|
||||
#include <basis/seadTypes.h>
|
||||
#include <time/seadTickSpan.h>
|
||||
#include "KingSystem/Utils/Types.h"
|
||||
|
||||
namespace ksys::util {
|
||||
|
||||
class ManagedTask;
|
||||
class TaskQueueBase;
|
||||
|
||||
class ManagedTaskHandle {
|
||||
public:
|
||||
enum class Status {
|
||||
Uninitialized = 0,
|
||||
TaskAttached = 1,
|
||||
TaskFinished = 2,
|
||||
TaskRemoved = 3,
|
||||
};
|
||||
|
||||
ManagedTaskHandle();
|
||||
virtual ~ManagedTaskHandle();
|
||||
|
||||
void finalize();
|
||||
|
||||
Status getStatus() const { return mStatus; }
|
||||
|
||||
void removeTaskFromQueue();
|
||||
bool hasTask() const;
|
||||
|
||||
bool wait();
|
||||
bool wait(const sead::TickSpan& wait_duration);
|
||||
|
||||
bool isTaskAttached() const;
|
||||
bool didTaskCompleteSuccessfully() const;
|
||||
|
||||
private:
|
||||
friend class ManagedTask;
|
||||
|
||||
struct SetTaskArg {
|
||||
ManagedTask* task;
|
||||
TaskQueueBase* queue;
|
||||
};
|
||||
|
||||
bool attachTask(const SetTaskArg& arg);
|
||||
void setIsSuccess(bool success);
|
||||
void setStatus(Status status);
|
||||
|
||||
void incrementRef_();
|
||||
void decrementRef_();
|
||||
|
||||
bool mSuccess = false;
|
||||
Status mStatus = Status::Uninitialized;
|
||||
s32 mRefCount = 0;
|
||||
ManagedTask* mTask = nullptr;
|
||||
TaskQueueBase* mQueue = nullptr;
|
||||
};
|
||||
KSYS_CHECK_SIZE_NX150(ManagedTaskHandle, 0x28);
|
||||
|
||||
} // namespace ksys::util
|
|
@ -0,0 +1,212 @@
|
|||
#include "KingSystem/Utils/Thread/TaskMgr.h"
|
||||
#include <heap/seadHeap.h>
|
||||
#include <heap/seadHeapMgr.h>
|
||||
#include "KingSystem/Utils/Thread/ManagedTask.h"
|
||||
#include "KingSystem/Utils/Thread/TaskThread.h"
|
||||
|
||||
namespace ksys::util {
|
||||
|
||||
TaskMgr::TaskMgr(sead::Heap* heap)
|
||||
: mTasksCS(heap), mCS2(heap), mNewFreeTaskEvent(heap, true), mEvent2(heap, true) {
|
||||
mFreeTaskLists[0].initOffset(ManagedTask::getListNodeOffset());
|
||||
mFreeTaskLists[1].initOffset(ManagedTask::getListNodeOffset());
|
||||
mNewFreeTaskEvent.resetSignal();
|
||||
}
|
||||
|
||||
TaskMgr::~TaskMgr() {
|
||||
finalize();
|
||||
}
|
||||
|
||||
void TaskMgr::finalize() {
|
||||
if (mFlags.isOn(Flag::HeapIsFreeable)) {
|
||||
if (mTask)
|
||||
delete mTask;
|
||||
mTask = nullptr;
|
||||
|
||||
for (auto*& task : mTasks) {
|
||||
if (task)
|
||||
delete task;
|
||||
task = nullptr;
|
||||
}
|
||||
|
||||
mTasks.freeBuffer();
|
||||
|
||||
} else {
|
||||
if (mTask) {
|
||||
mTask->~ManagedTask();
|
||||
mTask = nullptr;
|
||||
}
|
||||
|
||||
for (auto* task : mTasks)
|
||||
task->~ManagedTask();
|
||||
}
|
||||
}
|
||||
|
||||
void TaskMgr::submitRequest(TaskMgrRequest& request) {
|
||||
bool request_had_no_task = false;
|
||||
if (!request.task) {
|
||||
request_had_no_task = true;
|
||||
fetchIdleTaskForRequest_(request, true);
|
||||
}
|
||||
|
||||
if (!request.task)
|
||||
return;
|
||||
|
||||
auto* task = request.task;
|
||||
if (request.handle) {
|
||||
auto* queue = request.request->mQueue;
|
||||
if (!queue) {
|
||||
auto* thread = request.request->mThread;
|
||||
queue = thread ? thread->getTaskQueue() : nullptr;
|
||||
}
|
||||
task->attachHandle(request.handle, queue);
|
||||
} else {
|
||||
task->attachHandle(nullptr, nullptr);
|
||||
}
|
||||
|
||||
const bool ok = task->submitRequest(*request.request);
|
||||
if (!ok) {
|
||||
if (auto* managed_task = sead::DynamicCast<ManagedTask>(request.task)) {
|
||||
managed_task->attachHandle(nullptr, nullptr);
|
||||
if (!request_had_no_task)
|
||||
return;
|
||||
freeTask(managed_task);
|
||||
} else if (!request_had_no_task) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (request_had_no_task || !ok)
|
||||
request.task = nullptr;
|
||||
}
|
||||
|
||||
// NON_MATCHING: reorderings
|
||||
bool TaskMgr::fetchIdleTaskForRequest_(TaskMgrRequest& request, bool retry_until_success) {
|
||||
if (!hasTasks())
|
||||
return false;
|
||||
|
||||
ManagedTask* task = [this, retry_until_success] {
|
||||
const auto lock1 = sead::makeScopedLock(mTasksCS);
|
||||
if (auto* task = fetchIdleTask_(retry_until_success))
|
||||
return task;
|
||||
|
||||
swapLists_();
|
||||
if (!retry_until_success)
|
||||
return fetchIdleTask_(retry_until_success);
|
||||
|
||||
while (true) {
|
||||
if (auto* task_1 = fetchIdleTask_(retry_until_success))
|
||||
return task_1;
|
||||
mNewFreeTaskEvent.wait();
|
||||
swapLists_();
|
||||
}
|
||||
}();
|
||||
|
||||
if (!task)
|
||||
return false;
|
||||
|
||||
request.task = task;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TaskMgr::freeTask(ManagedTask* task) {
|
||||
auto lock = sead::makeScopedLock(mCS2);
|
||||
mFreeTaskLists[getListIndex2_()].pushBack(task);
|
||||
mNewFreeTaskEvent.setSignal();
|
||||
}
|
||||
|
||||
bool TaskMgr::trySubmitRequest(TaskMgrRequest& request) {
|
||||
bool request_had_no_task = false;
|
||||
if (!request.task) {
|
||||
request_had_no_task = true;
|
||||
if (!tryFetchTaskForRequest_(request, false))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!request.task)
|
||||
return false;
|
||||
|
||||
auto* task = request.task;
|
||||
if (request.handle) {
|
||||
auto* queue = request.request->mQueue;
|
||||
if (!queue) {
|
||||
auto* thread = request.request->mThread;
|
||||
queue = thread ? thread->getTaskQueue() : nullptr;
|
||||
}
|
||||
task->attachHandle(request.handle, queue);
|
||||
} else {
|
||||
task->attachHandle(nullptr, nullptr);
|
||||
}
|
||||
|
||||
const bool ok = task->submitRequest(*request.request);
|
||||
if (!ok) {
|
||||
if (auto* managed_task = sead::DynamicCast<ManagedTask>(request.task)) {
|
||||
managed_task->attachHandle(nullptr, nullptr);
|
||||
if (!request_had_no_task)
|
||||
return ok;
|
||||
freeTask(managed_task);
|
||||
} else if (!request_had_no_task) {
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
if (request_had_no_task || !ok)
|
||||
request.task = nullptr;
|
||||
return ok;
|
||||
}
|
||||
|
||||
// NON_MATCHING: the factory invoke function pointer is loaded earlier in the original code
|
||||
void TaskMgr::init(s32 num_tasks, sead::Heap* heap, ManagedTaskFactory& factory) {
|
||||
if (!heap->isFreeable())
|
||||
mFlags.reset(Flag::HeapIsFreeable);
|
||||
else
|
||||
mFlags.set(Flag::HeapIsFreeable);
|
||||
|
||||
const sead::ScopedCurrentHeapSetter heap_setter{heap};
|
||||
|
||||
mTasks.allocBufferAssert(num_tasks, heap);
|
||||
|
||||
if (mTasks.size() != 0) {
|
||||
auto& list = mFreeTaskLists[mListIndex];
|
||||
for (auto*& task : mTasks) {
|
||||
factory(&task);
|
||||
task->setMgr(this);
|
||||
list.pushBack(task);
|
||||
}
|
||||
}
|
||||
|
||||
factory(&mTask);
|
||||
}
|
||||
|
||||
bool TaskMgr::hasTasks() const {
|
||||
return mTasks.size() > 0;
|
||||
}
|
||||
|
||||
ManagedTask* TaskMgr::fetchIdleTask_(bool retry_until_success) {
|
||||
auto lock = sead::makeScopedLock(mTasksCS);
|
||||
|
||||
if (mFreeTaskLists[mListIndex].isEmpty())
|
||||
return nullptr;
|
||||
|
||||
ManagedTask* result = nullptr;
|
||||
while (true) {
|
||||
for (auto& task : mFreeTaskLists[mListIndex]) {
|
||||
if (task.isIdle()) {
|
||||
result = std::addressof(task);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
auto lock1 = sead::makeScopedLock(mTasksCS);
|
||||
mFreeTaskLists[mListIndex].erase(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!retry_until_success)
|
||||
return nullptr;
|
||||
mEvent2.wait(sead::TickSpan::fromMilliSeconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ksys::util
|
|
@ -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
|
Loading…
Reference in New Issue