diff options
| author | Léo Lam <leo@leolam.fr> | 2021-03-16 11:42:49 +0100 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2021-03-18 00:48:56 +0100 |
| commit | 298fa864910e86819a36fac1b8a62f45556de1bb (patch) | |
| tree | 5d8f6098c87784b1a7049125ab721648a5222f5d /src/KingSystem/ActorSystem/actBaseProcMgr.cpp | |
| parent | 7fc889714e7b057071a0d9a393946c0de97cd230 (diff) | |
ksys/act: Add more BaseProcMgr functions
Diffstat (limited to 'src/KingSystem/ActorSystem/actBaseProcMgr.cpp')
| -rw-r--r-- | src/KingSystem/ActorSystem/actBaseProcMgr.cpp | 242 |
1 files changed, 240 insertions, 2 deletions
diff --git a/src/KingSystem/ActorSystem/actBaseProcMgr.cpp b/src/KingSystem/ActorSystem/actBaseProcMgr.cpp index 0aaaaf69..bd228de3 100644 --- a/src/KingSystem/ActorSystem/actBaseProcMgr.cpp +++ b/src/KingSystem/ActorSystem/actBaseProcMgr.cpp @@ -339,7 +339,8 @@ void BaseProcMgr::unlockProcMap() { } void BaseProcMgr::deleteAllProcs() { - auto procs = getProcs(ProcFilter::_1 | ProcFilter::_4 | ProcFilter::_8); + auto procs = + getProcs(ProcFilter::Sleeping | ProcFilter::Initializing | ProcFilter::SkipAccessCheck); while (auto* proc = procs.next()) { if (!proc->mFlags.isOn(BaseProc::Flags::DoNotDelete)) proc->deleteLater(BaseProc::DeleteReason::BaseProcMgrDeleteAll); @@ -347,7 +348,8 @@ void BaseProcMgr::deleteAllProcs() { } bool BaseProcMgr::hasFinishedDeletingAllProcs() { - auto procs = getProcs(ProcFilter::_1 | ProcFilter::_2 | ProcFilter::_4 | ProcFilter::_8); + auto procs = getProcs(ProcFilter::Sleeping | ProcFilter::DeletedOrDeleting | + ProcFilter::Initializing | ProcFilter::SkipAccessCheck); while (auto* proc = procs.next()) { if (!proc->mFlags.isOn(BaseProc::Flags::DoNotDelete)) return false; @@ -369,6 +371,227 @@ bool BaseProcMgr::isHighPriorityThread() const { return id == mMainThreadId || id == mHavokThreadId1 || id == mHavokThreadId2; } +bool BaseProcMgr::isAccessingProcSafe(BaseProc* proc, BaseProc* other) const { + [[maybe_unused]] const auto current_thread = sead::ThreadMgr::instance()->getCurrentThread(); + + if (!isHighPriorityThread()) + return true; + + if (mUnk2) + return true; + + if (other) { + if (other == proc) + return true; + if (other->getConnectedCalcChild() == proc) + return true; + if (other->getConnectedCalcParent() == proc) + return true; + } + + if (!mIsPushingJobs) + return true; + + const auto type = mJobType; + + if (type == JobType::Invalid || mStatus != Status::ProcessingActorJobs) { +#ifdef MATCHING_HACK_NX_CLANG + if (proc->isInit()) { + fail: + return false; + } + return true; +#else + return !proc->isInit(); +#endif + } + + if (auto* handler = proc->getJobHandler(type)) { + u8 priority = handler->getLink().getPriority(); + while ((proc = proc->getConnectedCalcParent())) { + if (auto* h = proc->getJobHandler(type)) + priority = h->getLink().getPriority(); + } + if (mCurrentlyProcessingPrio != priority) + return true; + } else if (!proc->isInit()) { + return true; + } +#ifdef MATCHING_HACK_NX_CLANG + goto fail; +#else + return false; +#endif +} + +bool BaseProcMgr::requestCreateProc(const BaseProcCreateRequest& req) { + return mProcInitializer->requestCreateBaseProc(req); +} + +BaseProc* BaseProcMgr::createProc(const BaseProcCreateRequest& req) { + return mProcInitializer->createBaseProc(req); +} + +struct ProcForEachContextData { + inline void handle(BaseProcMapNode* node) const { + if (BaseProcMgr::instance()->checkFilters(node->proc(), filters)) + callback->invoke(node->proc()); + } + + BaseProcMgr::ProcFilters filters; + sead::IDelegate1<BaseProc*>* callback{}; +}; + +struct ProcForEachContext { + void forEach(util::StrTreeMapNode* node) { // NOLINT(readability-make-member-function-const) + for (auto it = static_cast<BaseProcMapNode*>(node); it; it = it->next()) + data->handle(it); + } + + ProcForEachContextData* data; +}; + +inline bool BaseProcMgr::checkFilters(BaseProc* proc, ProcFilters filters) const { + if (proc->isDeleting() && filters.isOff(ProcFilter::Deleting)) + return false; + + if (!proc->isInitialized() && filters.isOff(ProcFilter::Uninitialized)) + return false; + + if (proc->isSleep() && filters.isOff(ProcFilter::Sleeping)) + return false; + + if (proc->isDeletedOrDeleting() && filters.isOff(ProcFilter::DeletedOrDeleting)) + return false; + + if (proc->isInit() && filters.isOff(ProcFilter::Initializing)) + return false; + + return !filters.isOff(ProcFilter::SkipAccessCheck) || isAccessingProcSafe(proc, nullptr); +} + +BaseProc* BaseProcMgr::getProc(const sead::SafeString& name, BaseProcMgr::ProcFilters filters) { + const auto lock = sead::makeScopedLock(mProcMapCS); + + if (auto* node = mProcMap.find(name)) { + auto* proc = node->proc(); + if (checkFilters(proc, filters)) + return proc; + } + + return nullptr; +} + +BaseProc* BaseProcMgr::getProc(const u32& id, BaseProcMgr::ProcFilters filters) { + auto* cs = lockProcMap(); + auto guard = sead::makeScopeGuard([this] { unlockProcMap(); }); + + BaseProc* proc = nullptr; + do { + proc = getNextProc(cs, proc, filters); + if (proc && proc->getId() == id) { + if (!checkFilters(proc, filters)) + proc = nullptr; + break; + } + } while (proc); + return proc; +} + +// NON_MATCHING: stack +void BaseProcMgr::forEachProc(sead::IDelegate1<BaseProc*>& callback, ProcFilters filters) { + const auto lock = sead::makeScopedLock(mProcMapCS); + + ProcForEachContextData data; + ProcForEachContext context; + context.data = &data; + data.filters = filters; + data.callback = &callback; + + mProcMap.forEach(sead::Delegate1<ProcForEachContext, util::StrTreeMapNode*>( + &context, &ProcForEachContext::forEach)); +} + +void BaseProcMgr::forEachProc(const sead::SafeString& proc_name, + sead::IDelegate1<BaseProc*>& callback, + BaseProcMgr::ProcFilters filters) { + const auto lock = sead::makeScopedLock(mProcMapCS); + + BaseProc* proc = nullptr; + if (auto* node = mProcMap.find(proc_name)) + proc = node->proc(); + + while (proc) { + if (checkFilters(proc, filters)) + callback.invoke(proc); + + auto* next = proc->mMapNode.next(); + proc = next ? next->proc() : nullptr; + } +} + +bool BaseProcMgr::areInitializerThreadsIdle() const { + return !mProcInitializer->isAnyThreadActive(); +} + +void BaseProcMgr::waitForInitializerQueueToEmpty() { + mProcInitializer->waitForTaskQueuesToEmpty(); +} + +void BaseProcMgr::cancelInitializerTasks() { + mProcInitializer->cancelTasks(); +} + +void BaseProcMgr::blockInitializerTasks() { + mProcInitializer->blockPendingTasks(); +} + +void BaseProcMgr::restartInitializerThreads() { + blockInitializerTasks(); + mProcInitializer->restartThreads(); +} + +void BaseProcMgr::pauseInitializerThreads() { + mProcInitializer->pauseThreads(); +} + +void BaseProcMgr::resumeInitializerThreads() { + mProcInitializer->resumeThreads(); +} + +void BaseProcMgr::unblockInitDeleteTasks() { + mProcDeleter->unblockTasks(); + mProcInitializer->unblockPendingTasks(); +} + +void BaseProcMgr::pauseInitializerMainThread() { + mProcInitializer->pauseMainThread(); +} + +void BaseProcMgr::resumeInitializerMainThread() { + mProcInitializer->resumeMainThread(); +} + +bool BaseProcMgr::isAnyInitializerThreadActive() const { + return mProcInitializer->isAnyThreadActive(); +} + +int BaseProcMgr::getInitializerQueueSize() const { + return mProcInitializer->getQueueSize(); +} + +int BaseProcMgr::getInitializerQueueSizeEx(int x) const { + return mProcInitializer->getQueueSize(x); +} + +void BaseProcMgr::removeInitializerTasksIf(sead::IDelegate1R<util::Task*, bool>& predicate) { + mProcInitializer->removeTasksIf(predicate); +} + +void BaseProcMgr::setActorGenerationEnabled(bool enabled) { + mProcInitializer->setActorGenerationEnabled(enabled); +} + void BaseProcMgr::incrementUnk3() { if (mUnk3 != 0xFF) ++mUnk3; @@ -379,6 +602,21 @@ void BaseProcMgr::decrementUnk3() { --mUnk3; } +// NON_MATCHING: reorderings +void BaseProcMgr::queueExtraJobPush(BaseProcJobLink* job_link) { + getExtraJobs().pushBack(job_link); +} + +// NON_MATCHING: ??? +void BaseProcMgr::moveExtraJobsToOtherBuffer(JobType type) { + const auto old_idx = mCurrentExtraJobArrayIdx; + swapExtraJobArray(); + auto& array = mExtraJobLinkArrays.ref()[old_idx]; + for (auto& link : array) { + link.getProc()->queueExtraJobPush_(type, mCurrentExtraJobArrayIdx); + } +} + bool BaseProcMgr::hasExtraJobLink(BaseProcJobLink* job_link, s32 idx) { for (auto& ptr : mExtraJobLinkArrays.ref()[idx]) { if (&ptr == job_link) |
