summaryrefslogtreecommitdiff
path: root/src/KingSystem/ActorSystem
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2021-03-14 17:41:55 +0100
committerLéo Lam <leo@leolam.fr>2021-03-15 01:44:27 +0100
commiteef975f585f4cca8bbba89fc097d91dc620565ff (patch)
treec27d486c1626dd857c5c4a327b33d5fea1e65f16 /src/KingSystem/ActorSystem
parent20960b596fdc288ac4f4672bddba06c245987fb1 (diff)
ksys/act: Add more BaseProcMgr functions
Diffstat (limited to 'src/KingSystem/ActorSystem')
-rw-r--r--src/KingSystem/ActorSystem/actBaseProc.h1
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcInitializer.h2
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcJob.h5
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcJobQue.h2
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcMgr.cpp297
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcMgr.h67
6 files changed, 338 insertions, 36 deletions
diff --git a/src/KingSystem/ActorSystem/actBaseProc.h b/src/KingSystem/ActorSystem/actBaseProc.h
index c2712ed7..95097aee 100644
--- a/src/KingSystem/ActorSystem/actBaseProc.h
+++ b/src/KingSystem/ActorSystem/actBaseProc.h
@@ -41,6 +41,7 @@ public:
_0 = 0,
_1 = 1,
_2 = 2,
+ BaseProcMgrDeleteAll = 4,
_f = 0xf,
_15 = 0x15,
_16 = 0x16,
diff --git a/src/KingSystem/ActorSystem/actBaseProcInitializer.h b/src/KingSystem/ActorSystem/actBaseProcInitializer.h
index bd410fb9..fef07cb6 100644
--- a/src/KingSystem/ActorSystem/actBaseProcInitializer.h
+++ b/src/KingSystem/ActorSystem/actBaseProcInitializer.h
@@ -71,6 +71,8 @@ public:
void removeTasksIf(sead::IDelegate1R<util::Task*, bool>& predicate);
void setActorGenerationEnabled(bool enabled);
+ util::TaskQueue* getTaskQueue() const { return mTaskQueue; }
+
private:
sead::Buffer<ThreadInfo> mThreads;
util::TaskMgr* mTaskMgr = nullptr;
diff --git a/src/KingSystem/ActorSystem/actBaseProcJob.h b/src/KingSystem/ActorSystem/actBaseProcJob.h
index 705bbb38..41debba6 100644
--- a/src/KingSystem/ActorSystem/actBaseProcJob.h
+++ b/src/KingSystem/ActorSystem/actBaseProcJob.h
@@ -64,6 +64,9 @@ struct BaseProcJobList {
class BaseProcJobLists {
public:
+ BaseProcJobLists() = default;
+ ~BaseProcJobLists() { ; }
+
void pushJob(BaseProcJobLink& link);
void eraseJob(BaseProcJobLink& link);
sead::TListNode<BaseProc*>* getJobWithTopPriority() const;
@@ -73,7 +76,7 @@ public:
const BaseProcJobList& getList(int idx) const { return mLists[idx]; }
private:
- sead::SafeArray<BaseProcJobList, 8> mLists;
+ sead::SafeArray<BaseProcJobList, 8> mLists{};
};
class BaseProcJob final : public sead::Job {
diff --git a/src/KingSystem/ActorSystem/actBaseProcJobQue.h b/src/KingSystem/ActorSystem/actBaseProcJobQue.h
index 9a5dc27a..6d2aaf54 100644
--- a/src/KingSystem/ActorSystem/actBaseProcJobQue.h
+++ b/src/KingSystem/ActorSystem/actBaseProcJobQue.h
@@ -31,6 +31,8 @@ public:
bool pushExtraJobs(sead::FixedSizeJQ* queue,
const agl::utl::AtomicPtrArray<BaseProcJobLink>& links);
+ void clear() { mNumExtraJobs = 0; }
+
private:
bool pushJobs(sead::FixedSizeJQ* queue, BaseProcJobLists* lists, int priority,
bool should_reset_job_idx, JobType type);
diff --git a/src/KingSystem/ActorSystem/actBaseProcMgr.cpp b/src/KingSystem/ActorSystem/actBaseProcMgr.cpp
index 9f0044f7..0aaaaf69 100644
--- a/src/KingSystem/ActorSystem/actBaseProcMgr.cpp
+++ b/src/KingSystem/ActorSystem/actBaseProcMgr.cpp
@@ -1,6 +1,14 @@
#include "KingSystem/ActorSystem/actBaseProcMgr.h"
+#include <mc/seadWorkerMgr.h>
#include <prim/seadScopedLock.h>
#include <thread/seadThread.h>
+#include "KingSystem/ActorSystem/actActorSystem.h"
+#include "KingSystem/ActorSystem/actBaseProcDeleter.h"
+#include "KingSystem/ActorSystem/actBaseProcHeapMgr.h"
+#include "KingSystem/ActorSystem/actBaseProcInitializer.h"
+#include "KingSystem/ActorSystem/actBaseProcJobHandler.h"
+#include "KingSystem/ActorSystem/actBaseProcJobQue.h"
+#include "KingSystem/ActorSystem/actBaseProcLink.h"
namespace ksys::act {
@@ -11,6 +19,54 @@ BaseProcMgr::BaseProcMgr() {
mProcUpdateStateList.initOffset(offsetof(BaseProc, mUpdateStateListNode));
}
+BaseProcMgr::~BaseProcMgr() {
+ if (mProcJobQue) {
+ delete mProcJobQue;
+ mProcJobQue = nullptr;
+ }
+
+ mJobLists.freeBuffer();
+
+ if (mProcInitializer) {
+ delete mProcInitializer;
+ mProcInitializer = nullptr;
+ }
+
+ if (mProcDeleter) {
+ delete mProcDeleter;
+ mProcDeleter = nullptr;
+ }
+
+ BaseProcHeapMgr::deleteInstance();
+}
+
+// NON_MATCHING: mJobLists.allocBufferAssert - BaseProcJobLists ctor
+void BaseProcMgr::init(sead::Heap* heap, s32 num_job_types, u32 main_thread_id,
+ u32 havok_thread_id1, u32 havok_thread_id2,
+ const BaseProcInitializerArgs& initializer_args) {
+ mProcJobQue = new (heap) BaseProcJobQue;
+ mProcJobQue->init(heap);
+
+ mJobLists.allocBufferAssert(num_job_types, heap);
+
+ mProcInitializer = new (heap) BaseProcInitializer;
+ mProcInitializer->init(heap, initializer_args);
+
+ mProcDeleter = new (heap) BaseProcDeleter;
+ BaseProcDeleter::InitArg deleter_arg;
+ deleter_arg.heap = heap;
+ deleter_arg.task_queue = mProcInitializer->getTaskQueue();
+ deleter_arg.task_queue_size = 2048;
+ mProcDeleter->init(deleter_arg);
+
+ mMainThreadId = main_thread_id;
+ mHavokThreadId1 = havok_thread_id1;
+ mHavokThreadId2 = havok_thread_id2;
+
+ BaseProcHeapMgr::createInstance(heap);
+ BaseProcLinkDataMgr::createInstance(heap);
+}
+
void BaseProcMgr::generateProcId(u32* id) {
*id = mCreatedProcCounter.increment();
}
@@ -29,11 +85,52 @@ void BaseProcMgr::unregisterProc(BaseProc& proc) {
mProcMap.erase(&proc.mMapNode);
}
+bool BaseProcMgr::requestPreDelete(BaseProc& proc) {
+ return mProcDeleter->requestPreDelete(&proc);
+}
+
+void BaseProcMgr::requestUnloadActorParam(ActorParam* param) {
+ return mProcDeleter->requestUnloadActorParam(param);
+}
+
void BaseProcMgr::addToPreDeleteList(BaseProc& proc) {
auto lock = sead::makeScopedLock(mProcPreDeleteListCS);
mProcPreDeleteList.pushFront(&proc);
}
+void BaseProcMgr::eraseFromPreDeleteList(BaseProc& proc) {
+ auto lock = sead::makeScopedLock(mProcPreDeleteListCS);
+ if (mProcPreDeleteList.isNodeLinked(&proc))
+ mProcPreDeleteList.erase(&proc);
+}
+
+void BaseProcMgr::pushJob(BaseProc& proc, JobType type) {
+ if (proc.isSleep() || !proc.hasJobType_(type))
+ return;
+
+ getJobLists(type).pushJob(proc.getJobHandler(type)->getLink());
+}
+
+void BaseProcMgr::pushJobs(BaseProc& proc) {
+ for (u32 i = 0; i < u32(mJobLists.size()); ++i) {
+ pushJob(proc, JobType(i));
+ }
+}
+
+void BaseProcMgr::eraseJob(BaseProc& proc, JobType type) {
+ auto* handler = proc.getJobHandler(type);
+ if (handler)
+ getJobLists(type).eraseJob(handler->getLink());
+}
+
+void BaseProcMgr::eraseJobs(BaseProc& proc) {
+ for (u32 i = 0; i < u32(mJobLists.size()); ++i) {
+ auto* handler = proc.getJobHandler(JobType(i));
+ if (handler)
+ mJobLists[i].eraseJob(handler->getLink());
+ }
+}
+
void BaseProcMgr::doAddToUpdateStateList_(BaseProc& proc) {
if (mProcUpdateStateList.isNodeLinked(&proc))
return;
@@ -46,12 +143,6 @@ void BaseProcMgr::doAddToUpdateStateList_(BaseProc& proc) {
}
}
-void BaseProcMgr::eraseFromPreDeleteList(BaseProc& proc) {
- auto lock = sead::makeScopedLock(mProcPreDeleteListCS);
- if (mProcPreDeleteList.isNodeLinked(&proc))
- mProcPreDeleteList.erase(&proc);
-}
-
void BaseProcMgr::eraseFromUpdateStateList(BaseProc& proc) {
auto lock = sead::makeScopedLock(mProcUpdateStateListCS);
if (mProcUpdateStateList.isNodeLinked(&proc))
@@ -68,17 +159,100 @@ void BaseProcMgr::processPreDeleteList() {
mStatus = Status::Idle;
}
-bool BaseProcMgr::hasExtraJobLink(BaseProcJobLink* job_link, s32 idx) {
- for (auto& ptr : mExtraJobLinkArrays.ref()[idx]) {
- if (&ptr == job_link)
- return true;
+BaseProcMgr::ExtraJobLinkArray& BaseProcMgr::getExtraJobs() {
+ return mExtraJobLinkArrays.ref()[mCurrentExtraJobArrayIdx];
+}
+
+void BaseProcMgr::swapExtraJobArray() {
+ mCurrentExtraJobArrayIdx ^= 1;
+ getExtraJobs().clear();
+}
+
+bool BaseProcMgr::checkJobPushState() const {
+ return mEnableExtraJobPush && mUnk4 != 1;
+}
+
+void BaseProcMgr::pushJobQueues(sead::WorkerMgr* mgr, JobType type, bool x) {
+ if (!checkJobPushState())
+ return;
+
+ mJobType = type;
+ const auto type_ = mJobType;
+ mStatus = Status::ProcessingActorJobs;
+ mIsPushingJobs = true;
+ mUnk2 = x;
+
+ int i = 0;
+ do {
+ mPushActorJobType3InsteadOf6 = false;
+
+ auto& lists = getJobLists(type_);
+ for (int priority = 0; priority < 8; ++priority) {
+ mCurrentlyProcessingPrio = priority;
+ if (mProcJobQue->pushJobQueue(mgr, &lists, priority, type_)) {
+ mgr->run();
+ mgr->sync();
+ }
+ }
+
+ mCurrentlyProcessingPrio = 8;
+ ++i;
+ } while (mPushActorJobType3InsteadOf6 && i < 8);
+
+ mIsPushingJobs = false;
+ mUnk2 = false;
+ mStatus = Status::Idle;
+ mJobType = JobType::Invalid;
+}
+
+bool BaseProcMgr::pushExtraJobsEx(sead::FixedSizeJQ* jq, JobType type, u8 priority, bool x,
+ bool y) {
+ if (!checkJobPushState())
+ return false;
+
+ if (x) {
+ mUnk2 = y;
+ auto* queue = mProcJobQue;
+ mStatus = Status::ProcessingActorJobs;
+ mJobType = type;
+ mCurrentlyProcessingPrio = priority;
+ queue->clear();
}
- return false;
+
+ const auto type_ = JobType(u8(type));
+ mIsPushingJobs = true;
+ mProcJobQue->pushExtraJobs(jq, &getJobLists(type_), priority, type_);
+ return true;
}
-void BaseProcMgr::clearExtraJobArrays() {
- mExtraJobLinkArrays.ref()[0].clear();
- mExtraJobLinkArrays.ref()[1].clear();
+bool BaseProcMgr::pushExtraJobsForCurrentTypeAndPrio(sead::FixedSizeJQ* jq,
+ ExtraJobLinkArray* array) {
+ if (!checkJobPushState())
+ return false;
+ if (array)
+ mProcJobQue->pushExtraJobs(jq, *array);
+ return true;
+}
+
+void BaseProcMgr::setJobType(JobType type) {
+ mProcJobQue->clear();
+ mJobType = type;
+}
+
+bool BaseProcMgr::pushPreCalcJobs(sead::FixedSizeJQ* jq, JobType type, u8 prio, bool x, bool y) {
+ if (!checkJobPushState())
+ return false;
+
+ if (x) {
+ mStatus = Status::ProcessingActorJobs;
+ mJobType = type;
+ mCurrentlyProcessingPrio = prio;
+ mUnk2 = y;
+ }
+
+ const auto type_ = JobType(u8(type));
+ mProcJobQue->pushExtraJobs(jq, &getJobLists(type_), prio, type_);
+ return true;
}
void BaseProcMgr::setActorJobTypeAndPrio(JobType type, s32 prio, bool x) {
@@ -97,10 +271,90 @@ void BaseProcMgr::goIdle() {
mCurrentlyProcessingPrio = 8;
}
+void BaseProcMgr::jobInvoked(BaseProcJobLink* link, s32 required_calc_rounds) {
+ if (required_calc_rounds == 1) {
+ link->getProc()->jobInvoked(mJobType);
+ return;
+ }
+
+ const auto& lists = getJobLists(mJobType);
+ for (int i = 0; link && [&] { return i < required_calc_rounds; }(); ++i) {
+ link->getProc()->jobInvoked(mJobType);
+ link = static_cast<BaseProcJobLink*>(lists.getNextJob(link));
+ }
+}
+
+bool BaseProcMgr::isSpecialJobType(JobType type) const {
+ return mSpecialJobTypesMask.isOnBit(int(type));
+}
+
+void BaseProcMgr::addSpecialJobTypes(u16 mask) {
+ mSpecialJobTypesMask.set(mask);
+}
+
+void BaseProcMgr::removeSpecialJobTypes(u16 mask) {
+ mSpecialJobTypesMask.reset(mask);
+}
+
+void BaseProcMgr::calc() {
+ ActorSystem::instance()->onBaseProcMgrCalc();
+ mProcInitializer->deleteThreadIfPaused();
+
+ if (mIsInitialisingQuestMgrMaybe)
+ return;
+
+ if (!mProcUpdateStateList.isEmpty()) {
+ const auto lock = sead::makeScopedLock(mProcUpdateStateListCS);
+ mStatus = Status::ProcessingUpdateStateList;
+
+ for (auto& proc : mProcUpdateStateList)
+ proc.processStateUpdate(mCounter);
+
+ for (auto it = mProcUpdateStateList.robustBegin(), end = mProcUpdateStateList.robustEnd();
+ it != end; ++it) {
+ it->afterUpdateState_();
+ if (it->mStateFlags.isZero()) {
+ mProcUpdateStateList.erase(std::addressof(*it));
+ }
+ }
+
+ mStatus = Status::Idle;
+ }
+
+ ++mCounter;
+}
+
void BaseProcMgr::clearMode() {
mMode = Mode::_0;
}
+sead::CriticalSection* BaseProcMgr::lockProcMap() {
+ mProcMapCS.lock();
+ return &mProcMapCS;
+}
+
+void BaseProcMgr::unlockProcMap() {
+ mLastProcMapNode = nullptr;
+ mProcMapCS.unlock();
+}
+
+void BaseProcMgr::deleteAllProcs() {
+ auto procs = getProcs(ProcFilter::_1 | ProcFilter::_4 | ProcFilter::_8);
+ while (auto* proc = procs.next()) {
+ if (!proc->mFlags.isOn(BaseProc::Flags::DoNotDelete))
+ proc->deleteLater(BaseProc::DeleteReason::BaseProcMgrDeleteAll);
+ }
+}
+
+bool BaseProcMgr::hasFinishedDeletingAllProcs() {
+ auto procs = getProcs(ProcFilter::_1 | ProcFilter::_2 | ProcFilter::_4 | ProcFilter::_8);
+ while (auto* proc = procs.next()) {
+ if (!proc->mFlags.isOn(BaseProc::Flags::DoNotDelete))
+ return false;
+ }
+ return mNumPendingDeletions == 0;
+}
+
bool BaseProcMgr::isHighPriorityThread() const {
const auto current_thread = sead::ThreadMgr::instance()->getCurrentThread();
@@ -125,14 +379,17 @@ void BaseProcMgr::decrementUnk3() {
--mUnk3;
}
-sead::CriticalSection* BaseProcMgr::lockProcMap() {
- mProcMapCS.lock();
- return &mProcMapCS;
+bool BaseProcMgr::hasExtraJobLink(BaseProcJobLink* job_link, s32 idx) {
+ for (auto& ptr : mExtraJobLinkArrays.ref()[idx]) {
+ if (&ptr == job_link)
+ return true;
+ }
+ return false;
}
-void BaseProcMgr::unlockProcMap() {
- mLastProcMapNode = nullptr;
- mProcMapCS.unlock();
+void BaseProcMgr::clearExtraJobArrays() {
+ mExtraJobLinkArrays.ref()[0].clear();
+ mExtraJobLinkArrays.ref()[1].clear();
}
} // namespace ksys::act
diff --git a/src/KingSystem/ActorSystem/actBaseProcMgr.h b/src/KingSystem/ActorSystem/actBaseProcMgr.h
index 752da5b5..cbd6dddf 100644
--- a/src/KingSystem/ActorSystem/actBaseProcMgr.h
+++ b/src/KingSystem/ActorSystem/actBaseProcMgr.h
@@ -1,6 +1,7 @@
#pragma once
#include <agl/Utils/aglAtomicPtrArray.h>
+#include <container/seadBuffer.h>
#include <container/seadOffsetList.h>
#include <container/seadPtrArray.h>
#include <container/seadSafeArray.h>
@@ -20,13 +21,12 @@
namespace sead {
class FixedSizeJQ;
-template <typename F>
-class IFunction;
class WorkerMgr;
} // namespace sead
namespace ksys::act {
+class ActorParam;
class BaseProcCreateTaskData;
class BaseProcDeleter;
class BaseProcInitializer;
@@ -57,8 +57,34 @@ public:
_0 = 0,
};
+ enum class ProcFilter {
+ _1 = 1 << 0,
+ _2 = 1 << 1,
+ _4 = 1 << 2,
+ _8 = 1 << 3,
+ _10 = 1 << 4,
+ _20 = 1 << 5,
+ _40 = 1 << 6,
+ };
+
+ using ProcFilters = sead::TypedBitFlag<ProcFilter>;
using ExtraJobLinkArray = agl::utl::FixedPtrArray<BaseProcJobLink, 512>;
+ /// Wrapper to simplify BaseProc iteration.
+ class ProcIteratorContext {
+ public:
+ ProcIteratorContext(BaseProcMgr& mgr, ProcFilters filters)
+ : mMgr(mgr), mCS(mgr.lockProcMap()), mFilters(filters) {}
+ ~ProcIteratorContext() { mMgr.unlockProcMap(); }
+ BaseProc* next() { return mProc = mMgr.getNextProc(mCS, mProc, mFilters); }
+
+ private:
+ BaseProcMgr& mMgr;
+ sead::CriticalSection* mCS{};
+ ProcFilters mFilters{};
+ BaseProc* mProc{};
+ };
+
static void createInstanceAndInit(sead::Heap* heap);
static u32 getConstant0() { return sConstant0; }
static u32 getConstant1() { return sConstant1; }
@@ -92,7 +118,7 @@ public:
// endregion
bool requestPreDelete(BaseProc& proc);
- void requestUnloadActorParam(void*);
+ void requestUnloadActorParam(ActorParam* param);
// region Job processing
@@ -110,12 +136,12 @@ public:
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 pushJobQueues(sead::WorkerMgr* mgr, JobType type, bool x);
+ bool pushExtraJobsEx(sead::FixedSizeJQ* jq, JobType type, u8 priority, bool x, bool y);
+ bool pushExtraJobsForCurrentTypeAndPrio(sead::FixedSizeJQ* jq, ExtraJobLinkArray* array);
+ bool pushPreCalcJobs(sead::FixedSizeJQ* jq, JobType type, u8 prio, bool x, bool y);
- void setActorJobType(JobType type);
+ void setJobType(JobType type);
void setActorJobTypeAndPrio(JobType type, s32 prio, bool);
void goIdle();
void clearMode();
@@ -172,17 +198,25 @@ public:
Status getStatus() const { return mStatus; }
JobType getJobType() const { return mJobType; }
- u32 getNumJobTypes() const { return mNumJobTypes; }
+ u32 getNumJobTypes() const { return mJobLists.size(); }
+ BaseProcJobLists& getJobLists(JobType type) { return mJobLists[u32(type)]; }
bool isPushingJobs() const { return mIsPushingJobs; }
bool checkGetActorOk(BaseProc* proc, void* a2);
-private:
- void doAddToUpdateStateList_(BaseProc& proc);
+ // region BaseProc iteration
sead::CriticalSection* lockProcMap();
void unlockProcMap();
- void getNextActor(sead::CriticalSection* cs, BaseProc* proc, u32 flags);
+ BaseProc* getNextProc(sead::CriticalSection* cs, BaseProc* proc, ProcFilters filters);
+ ProcIteratorContext getProcs(ProcFilter filters) { return {*this, filters}; }
+
+ // endregion
+
+private:
+ void doAddToUpdateStateList_(BaseProc& proc);
+
+ bool checkJobPushState() const;
static sead::BufferedSafeString* sResidentActorListStr;
static u32 sConstant0;
@@ -196,8 +230,7 @@ private:
u8 mCounter = 0;
sead::CriticalSection mProcMapCS;
sead::OffsetList<BaseProc> mProcPreDeleteList;
- u32 mNumJobTypes = 0;
- BaseProcJobLists* mJobLists = nullptr;
+ sead::Buffer<BaseProcJobLists> mJobLists;
BaseProcMap mProcMap;
sead::OffsetList<BaseProc> mProcUpdateStateList;
sead::CriticalSection mProcUpdateStateListCS;
@@ -214,7 +247,7 @@ private:
Mode mMode = Mode::_0;
bool mUnk2 = false;
bool mIsInitialisingQuestMgrMaybe = false;
- u8 mCurrentExtraJobArrayIdx = 0;
+ s8 mCurrentExtraJobArrayIdx = 0;
u8 mUnk3 = 0;
sead::BitFlag16 mSpecialJobTypesMask = 0;
u32 mMainThreadId = 0;
@@ -226,6 +259,10 @@ private:
};
KSYS_CHECK_SIZE_NX150(BaseProcMgr, 0x21a0);
+constexpr auto operator|(BaseProcMgr::ProcFilter a, BaseProcMgr::ProcFilter b) {
+ return BaseProcMgr::ProcFilter(u32(a) | u32(b));
+}
+
inline bool BaseProcMgr::setProcFlag(BaseProc& proc, BaseProc::StateFlags flag) {
auto lock = sead::makeScopedLock(mProcUpdateStateListCS);
doAddToUpdateStateList_(proc);