summaryrefslogtreecommitdiff
path: root/src/KingSystem/ActorSystem/actBaseProcMgr.h
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2020-06-05 17:09:06 +0200
committerLéo Lam <leo@leolam.fr>2020-08-18 22:50:25 +0200
commit2de366be0fa75e571c605e017b5604bccbdb75bf (patch)
treeb8044fc96bba792b1875067032da2fd4498a44a3 /src/KingSystem/ActorSystem/actBaseProcMgr.h
Initial commit
Diffstat (limited to 'src/KingSystem/ActorSystem/actBaseProcMgr.h')
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcMgr.h219
1 files changed, 219 insertions, 0 deletions
diff --git a/src/KingSystem/ActorSystem/actBaseProcMgr.h b/src/KingSystem/ActorSystem/actBaseProcMgr.h
new file mode 100644
index 00000000..95d79f9b
--- /dev/null
+++ b/src/KingSystem/ActorSystem/actBaseProcMgr.h
@@ -0,0 +1,219 @@
+#pragma once
+
+#include <agl/Utils/aglAtomicPtrArray.h>
+#include <container/seadOffsetList.h>
+#include <container/seadPtrArray.h>
+#include <container/seadSafeArray.h>
+#include <heap/seadDisposer.h>
+#include <prim/seadBitFlag.h>
+#include <prim/seadScopedLock.h>
+#include <thread/seadAtomic.h>
+#include <thread/seadCriticalSection.h>
+#include "KingSystem/ActorSystem/actBaseProc.h"
+#include "KingSystem/ActorSystem/actBaseProcJob.h"
+#include "KingSystem/ActorSystem/actBaseProcMap.h"
+#include "KingSystem/Utils/StrTreeMap.h"
+#include "KingSystem/Utils/Types.h"
+
+namespace sead {
+class FixedSizeJQ;
+template <typename F>
+class IFunction;
+class WorkerMgr;
+} // namespace sead
+
+namespace ksys::act {
+
+class BaseProcDeleter;
+class BaseProcInitializer;
+class BaseProcInitializerArgs;
+class BaseProcJobLists;
+class BaseProcJobQue;
+
+class BaseProcMgr {
+ SEAD_SINGLETON_DISPOSER(BaseProcMgr)
+ BaseProcMgr();
+
+public:
+ class ProcCreateRequest;
+
+ enum class Status : u8 {
+ Idle = 0,
+ _1 = 1,
+ ProcessingActorJobs = 2,
+ ProcessingPreDeleteList = 3,
+ ProcessingUpdateStateList = 4,
+ };
+
+ enum class Mode : u8 {
+ _0 = 0,
+ };
+
+ using ExtraJobLinkArray = agl::utl::FixedPtrArray<BaseProcJobLink, 512>;
+
+ static void createInstanceAndInit(sead::Heap* heap);
+ static u32 getConstant0() { return sConstant0; }
+ static u32 getConstant1() { return sConstant1; }
+ static u32 getConstant2() { return sConstant2; }
+ static u32 getConstant4() { return sConstant4; }
+
+ virtual ~BaseProcMgr();
+
+ void init(sead::Heap* heap, s32 num_job_types, u32 main_thread_id, u32 havok_thread_id1,
+ u32 havok_thread_id2, BaseProcInitializerArgs* initializer_args);
+
+ // region BaseProc management
+
+ void generateProcId(u32* id);
+ void registerProc(BaseProc& proc);
+ void unregisterProc(BaseProc& proc);
+
+ void addToPreDeleteList(BaseProc& proc);
+ bool addToUpdateStateList(BaseProc& proc);
+ void eraseFromPreDeleteList(BaseProc& proc);
+ void eraseFromUpdateStateList(BaseProc& proc);
+ void processPreDeleteList();
+
+ void forEachProc(const sead::IDelegate1<BaseProc*>& callback, u32 flags);
+ void deleteAllProcs();
+ bool hasFinishedDeletingAllProcs();
+
+ // endregion
+
+ bool requestPreDelete(BaseProc& proc);
+ void requestUnloadActorParam(void*);
+
+ // region Job processing
+
+ void pushJob(BaseProc& proc, JobType type);
+ void pushJobs(BaseProc& proc);
+ void eraseJob(BaseProc& proc, JobType type);
+ void eraseJobs(BaseProc& proc);
+
+ void processExtraJobsDirectly(JobType type, s32 prio, bool);
+ ExtraJobLinkArray& getExtraJobs();
+ void swapExtraJobArray();
+
+ void queueExtraJobPush(BaseProcJobLink* job_link);
+ void moveExtraJobsToOtherBuffer();
+ bool hasExtraJobLink(BaseProcJobLink* job_link, s32 idx);
+ void clearExtraJobArrays();
+
+ void pushJobQueues(sead::WorkerMgr* mgr, JobType type, bool);
+ bool pushExtraJobsEx(sead::FixedSizeJQ* jq, JobType type, bool, bool);
+ bool pushExtraJobsForCurrentTypeAndPrio(sead::FixedSizeJQ* jq, ExtraJobLinkArray& array);
+ bool pushPreCalcJobs(sead::FixedSizeJQ* jq, JobType type, s32 prio, bool, bool);
+
+ void setActorJobType(JobType type);
+ void setActorJobTypeAndPrio(JobType type, s32 prio, bool);
+ void goIdle();
+ void clearMode();
+ void calc();
+ void jobInvoked(BaseProcJobLink* link, s32 required_calc_rounds);
+
+ // endregion
+
+ // region Special job types
+
+ bool isSpecialJobType(JobType type) const;
+ void addSpecialJobTypes(u16 mask);
+ void removeSpecialJobTypes(u16 mask);
+
+ // endregion
+
+ /// Returns true if and only if the calling thread is the game thread or a Havok thread.
+ bool isHighPriorityThread() const;
+ /// Returns true if and only if it is safe to access the specified BaseProc.
+ bool isAccessingProcSafe(BaseProc* proc, BaseProc* other);
+
+ // region BaseProc creation
+
+ bool requestCreateProc(ProcCreateRequest& req);
+ BaseProc* createProc(ProcCreateRequest& req);
+
+ // endregion
+
+ // region Actor initializer control
+
+ void resumeThreadMaybe();
+ void stopThreads();
+ void clearMessageQueueMaybe();
+ void startActorCreateThread();
+
+ void clearInitializerMessageQueuesMaybe();
+ s32 getActorCreateInitializerQueueSize();
+ s32 getActorCreateInitializerQueueSizeEx(s32 x);
+ void invokeOnActorCreateInitializerThreadMaybe(void* delegate);
+ void setActorGenerationEnabled(bool enabled);
+
+ // endregion
+
+ auto getUnk3() const { return mUnk3; }
+ void incrementUnk3();
+ void decrementUnk3();
+
+ void writeResidentActorsCsv(const sead::SafeString& file_path);
+
+ auto& getProcUpdateStateListCS() { return mProcUpdateStateListCS; }
+
+ void incrementPendingDeletions() { mNumPendingDeletions.increment(); }
+ void decrementPendingDeletions() { mNumPendingDeletions.decrement(); }
+
+ u32 getNumJobTypes() const { return mNumJobTypes; }
+
+private:
+ void doAddToUpdateStateList_(BaseProc& proc);
+
+ sead::CriticalSection* lockProcMap();
+ void unlockProcMap();
+ void getNextActor(sead::CriticalSection* cs, BaseProc* proc, u32 flags);
+
+ static sead::BufferedSafeString* sResidentActorListStr;
+ static u32 sConstant0;
+ static u32 sConstant1;
+ static u32 sConstant2;
+ static u32 sConstant4;
+
+ Status mStatus = Status::Idle;
+ util::SizedEnum<JobType, u8> mJobType = JobType::Invalid;
+ u8 mCurrentlyProcessingPrio = 8;
+ u8 mCounter = 0;
+ sead::CriticalSection mProcMapCS;
+ sead::OffsetList<BaseProc> mProcPreDeleteList;
+ u32 mNumJobTypes = 0;
+ BaseProcJobLists* mJobLists = nullptr;
+ BaseProcMap mProcMap;
+ sead::OffsetList<BaseProc> mProcUpdateStateList;
+ sead::CriticalSection mProcUpdateStateListCS;
+ sead::CriticalSection mProcPreDeleteListCS;
+ BaseProcMapNode* mLastProcMapNode = nullptr;
+ BaseProcJobQue* mProcJobQue = nullptr;
+ sead::Atomic<u32> mCreatedProcCounter = 0;
+ sead::Atomic<u32> mNumPendingDeletions = 0;
+ BaseProcInitializer* mProcInitializer = nullptr;
+ BaseProcDeleter* mProcDeleter = nullptr;
+ bool mIsPushingJobs = false;
+ bool mPushActorJobType3InsteadOf6 = false;
+ bool mEnableExtraJobPush = false;
+ Mode mMode = Mode::_0;
+ bool mUnk2 = false;
+ bool mIsInitialisingQuestMgrMaybe = false;
+ u8 mCurrentExtraJobArrayIdx = 0;
+ u8 mUnk3 = 0;
+ sead::BitFlag16 mSpecialJobTypesMask = 0;
+ u32 mMainThreadId = 0;
+ u32 mHavokThreadId1 = 0;
+ u32 mHavokThreadId2 = 0;
+ u32 mUnk4 = 0;
+ sead::SafeArray<ExtraJobLinkArray, 2> mExtraJobLinkArrays{};
+};
+KSYS_CHECK_SIZE_NX150(BaseProcMgr, 0x21a0);
+
+inline bool BaseProcMgr::addToUpdateStateList(BaseProc& proc) {
+ auto lock = sead::makeScopedLock(mProcUpdateStateListCS);
+ doAddToUpdateStateList_(proc);
+ return (proc.mStateFlags.set(BaseProc::StateFlags::RequestDelete) &
+ u32(BaseProc::StateFlags::RequestDelete)) != 0;
+}
+
+} // namespace ksys::act