diff options
| author | Léo Lam <leo@leolam.fr> | 2021-02-06 16:33:10 +0100 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2021-02-07 00:13:55 +0100 |
| commit | 5f5c27a0782cda67115197f8fe2ca2588b6e4a22 (patch) | |
| tree | b30082fdfd1e4c326be24bf4291d086ab7aed018 /src/KingSystem/ActorSystem/actBaseProc.cpp | |
| parent | 123e27528329df4e9afcd3fe5ed5dd513fddabad (diff) | |
ksys/act: Implement remaining BaseProc functions
Diffstat (limited to 'src/KingSystem/ActorSystem/actBaseProc.cpp')
| -rw-r--r-- | src/KingSystem/ActorSystem/actBaseProc.cpp | 251 |
1 files changed, 246 insertions, 5 deletions
diff --git a/src/KingSystem/ActorSystem/actBaseProc.cpp b/src/KingSystem/ActorSystem/actBaseProc.cpp index b0a94ed3..b6fc7f16 100644 --- a/src/KingSystem/ActorSystem/actBaseProc.cpp +++ b/src/KingSystem/ActorSystem/actBaseProc.cpp @@ -1,4 +1,7 @@ #include "KingSystem/ActorSystem/actBaseProc.h" +#include <thread/seadThread.h> +#include <time/seadTickSpan.h> +#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" #include "KingSystem/ActorSystem/actBaseProcJobHandler.h" #include "KingSystem/ActorSystem/actBaseProcLink.h" #include "KingSystem/ActorSystem/actBaseProcMgr.h" @@ -47,6 +50,50 @@ bool BaseProc::init(sead::Heap* heap, bool sleep_after_init) { return context.result == InitResult::Ok && mStateFlags.isOff(StateFlags::RequestDelete); } +void BaseProc::sleep(BaseProc::SleepWakeReason reason) { + if (isDeletedOrDeleting()) + return; + + const auto lock = sead::makeScopedLock(BaseProcMgr::instance()->getProcUpdateStateListCS()); + + const bool reason_changed = mFlags.getStorage().setBitOn(int(reason) + 10); + const auto state = mState; + + bool requested = mStateFlags.reset(StateFlags::RequestWakeUp); + if (state != State::Sleep) + requested = BaseProcMgr::instance()->setProcFlag(*this, StateFlags::RequestSleep); + + if (reason_changed || requested) + onSleepRequested_(reason); +} + +void BaseProc::wakeUp(BaseProc::SleepWakeReason reason) { + if (isDeletedOrDeleting()) + return; + + const auto lock = sead::makeScopedLock(BaseProcMgr::instance()->getProcUpdateStateListCS()); + + const bool reason_changed = mFlags.getStorage().setBitOff(int(reason) + 10); + if (mFlags.isOn(Flags::SleepWakeReasonAny)) { + if (reason_changed) + onWakeUpRequested_(reason); + } else if (isInit() || isSleep()) { + mStateFlags.reset(StateFlags::RequestSleep); + bool requested = BaseProcMgr::instance()->setProcFlag(*this, StateFlags::RequestWakeUp); + if (reason_changed || requested) + onWakeUpRequested_(reason); + } else { + bool cancelled_sleep = mStateFlags.reset(StateFlags::RequestSleep); + if (reason_changed || cancelled_sleep) + onWakeUpRequested_(reason); + } + + if (mProcUnit && !mProcUnit->isParentHandleDefault()) { + sead::FixedSafeString<0x100> message; + message.format("BaseProcUnit:%p BaseProc(%s:%p)", mProcUnit, mName.cstr(), this); + } +} + bool BaseProc::deleteLater(DeleteReason reason) { if (isDeletedOrDeleting()) return false; @@ -66,7 +113,7 @@ bool BaseProc::deleteLater(DeleteReason reason) { } } - if (!BaseProcMgr::instance()->addToUpdateStateList(*this, StateFlags::RequestDelete)) + if (BaseProcMgr::instance()->setProcFlag(*this, StateFlags::RequestDelete)) onDeleteRequested_(reason); if (!is_high_prio) @@ -161,6 +208,23 @@ BaseProc::IsSpecialJobTypeResult BaseProc::isSpecialJobType_(JobType type) { return IsSpecialJobTypeResult::No; } +bool BaseProc::isSpecialJobType(JobType type) { + if (isSpecialJobType_(type) != IsSpecialJobTypeResult::No) + return true; + + const auto check = [&](auto self, BaseProc* proc) { + if (!proc) + return false; + const auto result = proc->isSpecialJobType_(type); + if (result == IsSpecialJobTypeResult::Yes) + return true; + if (result == IsSpecialJobTypeResult::_2) + return false; + return self(self, proc->mConnectedCalcParent); + }; + return check(check, mConnectedCalcParent); +} + bool BaseProc::canWakeUp_() { return true; } @@ -170,6 +234,56 @@ void BaseProc::queueExtraJobPush_(JobType type) { BaseProcMgr::instance()->queueExtraJobPush(&mJobHandlers[int(type)]->getLink()); } +bool BaseProc::shouldSkipJobPush(JobType type) { + bool skip = mSkippedJobTypesMask.isOnBit(int(type)) || shouldSkipJobPush_(type); + + BaseProc* proc = this; + while ((proc = proc->mConnectedCalcParent)) { + if (proc->getState() == State::Delete) + break; + skip = proc->mSkippedJobTypesMask.isOnBit(int(type)) || proc->shouldSkipJobPush_(type); + } + return skip; +} + +inline void BaseProc::setJobPriorityDuringCalc_(BaseProcJobHandler*& handler, JobType type) { + BaseProcMgr* mgr = BaseProcMgr::instance(); + if (mgr->isPushingJobs() || mgr->getJobType() == type) { + mgr->setProcFlag(*this, StateFlags::RequestChangeCalcJobPriority); + } else { + BaseProcMgr::instance()->eraseJob(*this, type); + handler->getLink().loadNewPriority(); + handler->getLink().loadNewPriority2(); + BaseProcMgr::instance()->pushJob(*this, type); + } +} + +void BaseProc::setJobPriority(u8 actorparam_priority, JobType type) { + if (isDeletedOrDeleting()) + return; + + auto& handler = mJobHandlers[int(type)]; + handler->getLink().setNewPriority(actorparam_priority); + if (isCalc()) { + setJobPriorityDuringCalc_(handler, type); + } else { + handler->getLink().loadNewPriority(); + } +} + +void BaseProc::setJobPriority2(u8 actorparam_priority, JobType type) { + if (isDeletedOrDeleting()) + return; + + auto& handler = mJobHandlers[int(type)]; + handler->getLink().setNewPriority2(actorparam_priority); + if (isCalc()) { + setJobPriorityDuringCalc_(handler, type); + } else { + handler->getLink().loadNewPriority2(); + } +} + bool BaseProc::hasJobType_(JobType type) { return mJobHandlers[int(type)] != nullptr; } @@ -187,6 +301,51 @@ void BaseProc::onJobPush1_(JobType) {} void BaseProc::onJobPush2_(JobType) {} +void BaseProc::jobInvoked(JobType type) { + for (auto* proc = mConnectedCalcParent; proc; proc = proc->mConnectedCalcParent) { + if (proc->hasJobType_(type)) + return; + } + + IsSpecialJobTypeResult special; + + if (mStateFlags.isOn(StateFlags::RequestDelete)) { + if (type == JobType::Calc4) + mJobHandlers[4]->invoke(); + special = IsSpecialJobTypeResult::Yes; + } else { + special = isSpecialJobType_(type); + auto* handler = mJobHandlers[int(type)]; + if (special != IsSpecialJobTypeResult::No) + handler->invokeSpecial(); + else + handler->invoke(); + } + + for (auto* child = mConnectedCalcChild; child; child = child->mConnectedCalcChild) { + if (!child->hasJobType_(type) || !child->isCalc()) + continue; + + const auto child_special = child->isSpecialJobType_(type); + if (child->mStateFlags.isOn(StateFlags::RequestDelete)) { + if (type == JobType::Calc4) + child->mJobHandlers[4]->invoke(); + special = IsSpecialJobTypeResult::Yes; + } else { + auto* handler = child->mJobHandlers[int(type)]; + if (special == IsSpecialJobTypeResult::Yes || + child_special != IsSpecialJobTypeResult::No) { + handler->invokeSpecial(); + special = child_special != IsSpecialJobTypeResult::No ? child_special : + IsSpecialJobTypeResult::Yes; + } else { + handler->invoke(); + special = IsSpecialJobTypeResult::No; + } + } + } +} + // NON_MATCHING: branching bool BaseProc::processStateUpdate(u8 counter) { const bool delete_requested = mStateFlags.isOn(StateFlags::RequestDelete); @@ -312,6 +471,10 @@ void BaseProc::processPreDelete() { } } +void BaseProc::freeLinkData() { + BaseProcLinkDataMgr::instance()->releaseLink(this); +} + void BaseProc::doPreDelete(bool* do_not_destruct_immediately) { preDelete1_(); preDelete2_(do_not_destruct_immediately); @@ -425,11 +588,81 @@ bool BaseProc::x00000071011ba9fc() { return true; } +bool BaseProc::setStateFlag(u32 flag_bit) { + return BaseProcMgr::instance()->setProcFlag(*this, flag_bit); +} + +bool BaseProc::acquire(ActorLinkConstDataAccess& accessor) { + if (mState == State::Delete) + return false; + + if (!BaseProcMgr::instance()->isHighPriorityThread()) { + int ref_count = std::max(0, mRefCount.load()); + int current_ref_count; + while (!mRefCount.compareExchange(ref_count, ref_count + 1, ¤t_ref_count)) { + if (current_ref_count == -1) + return false; + + sead::TickSpan span; + span.setNanoSeconds(1); + sead::Thread::sleep(span); + ref_count = current_ref_count; + } + accessor.mAcquired = true; + } + + accessor.mProc = this; + return true; +} + void BaseProc::release() { if (mRefCount >= 1) mRefCount--; } +void BaseProc::startDelete_() { + BaseProcMgr::instance()->incrementPendingDeletions(); + + mState = State::Delete; + + if (mConnectedCalcChildNew) { + if (mFlags.isOn(Flags::DeleteChildOnDelete)) + mConnectedCalcChildNew->deleteLater(DeleteReason::_18); + mConnectedCalcChildNew = nullptr; + } + + if (mConnectedCalcParentNew) { + if (mFlags.isOn(Flags::DeleteParentOnDelete)) + mConnectedCalcParentNew->deleteLater(DeleteReason::_19); + mConnectedCalcParentNew = nullptr; + } + + if (mConnectedCalcChild) { + if (mFlags.isOn(Flags::DeleteChildOnDelete)) + mConnectedCalcChild->deleteLater(DeleteReason::_16); + if (mConnectedCalcChild) { + mConnectedCalcChild->mConnectedCalcParent = nullptr; + mConnectedCalcChild = nullptr; + } + } + + if (mConnectedCalcParent) { + if (mFlags.isOn(Flags::DeleteParentOnDelete)) + mConnectedCalcParent->deleteLater(DeleteReason::_17); + if (auto& child = mConnectedCalcParent->mConnectedCalcChild) { + child->mConnectedCalcParent = nullptr; + child = nullptr; + } + } + + if (mProcUnit) { + mProcUnit->cleanUp(this, false); + mProcUnit = nullptr; + } + + onEnterDelete_(); +} + BaseProc* BaseProc::getConnectedCalcParent() const { if (mConnectedCalcParent == nullptr || mConnectedCalcParent->mState == State::Delete) return nullptr; @@ -444,7 +677,7 @@ bool BaseProc::setConnectedCalcParent(BaseProc* parent, bool delete_parent_on_de if (isDeletedOrDeleting() || parent->isDeletedOrDeleting()) return false; - if (BaseProcMgr::instance()->addToUpdateStateList(*this, StateFlags::RequestSetParent)) + if (!BaseProcMgr::instance()->setProcFlag(*this, StateFlags::RequestSetParent)) return false; mConnectedCalcParentNew = parent; @@ -464,7 +697,7 @@ void BaseProc::resetConnectedCalcParent(bool clear_existing_set_request) { } if (mConnectedCalcParent) - BaseProcMgr::instance()->addToUpdateStateList(*this, StateFlags::RequestResetParent); + BaseProcMgr::instance()->setProcFlag(*this, StateFlags::RequestResetParent); } BaseProc* BaseProc::getConnectedCalcChild() const { @@ -481,7 +714,7 @@ bool BaseProc::setConnectedCalcChild(BaseProc* child, bool delete_child_on_delet if (isDeletedOrDeleting() || child->isDeletedOrDeleting()) return false; - if (BaseProcMgr::instance()->addToUpdateStateList(*this, StateFlags::RequestSetChild)) + if (!BaseProcMgr::instance()->setProcFlag(*this, StateFlags::RequestSetChild)) return false; mConnectedCalcChildNew = child; @@ -501,7 +734,15 @@ void BaseProc::resetConnectedCalcChild(bool clear_existing_set_request) { } if (mConnectedCalcChild) - BaseProcMgr::instance()->addToUpdateStateList(*this, StateFlags::RequestResetChild); + BaseProcMgr::instance()->setProcFlag(*this, StateFlags::RequestResetChild); +} + +void BaseProc::setCreatePriorityState1() { + mCreatePriorityState = 1; +} + +void BaseProc::setCreatePriorityState2() { + mCreatePriorityState = 2; } } // namespace ksys::act |
