diff options
| author | Léo Lam <leo@leolam.fr> | 2021-03-14 14:05:38 +0100 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2021-03-14 17:11:38 +0100 |
| commit | 4f2c0a60798d07bc77121e4ef02fbf17075c52da (patch) | |
| tree | 8e6da2b84da5ea999480c00d32167f254150cdc2 /src/KingSystem/ActorSystem/actBaseProcHandle.cpp | |
| parent | e36bc464b6fb19e80a1755b469b8a29295d080cc (diff) | |
ksys/act: Finish BaseProcHandle
Diffstat (limited to 'src/KingSystem/ActorSystem/actBaseProcHandle.cpp')
| -rw-r--r-- | src/KingSystem/ActorSystem/actBaseProcHandle.cpp | 154 |
1 files changed, 144 insertions, 10 deletions
diff --git a/src/KingSystem/ActorSystem/actBaseProcHandle.cpp b/src/KingSystem/ActorSystem/actBaseProcHandle.cpp index 35a1b13d..95cfa803 100644 --- a/src/KingSystem/ActorSystem/actBaseProcHandle.cpp +++ b/src/KingSystem/ActorSystem/actBaseProcHandle.cpp @@ -1,4 +1,7 @@ #include "KingSystem/ActorSystem/actBaseProcHandle.h" +#include <prim/seadScopedLock.h> +#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" +#include "KingSystem/ActorSystem/actBaseProc.h" #include "KingSystem/ActorSystem/actBaseProcUnit.h" #include "KingSystem/Utils/InitTimeInfo.h" @@ -6,28 +9,159 @@ namespace ksys::act { static util::InitTimeInfo sInfo; -BaseProcHandle::BaseProcHandle() { - mUnit = nullptr; - mFlag = 0; -} +BaseProcHandle::BaseProcHandle() = default; BaseProcHandle::~BaseProcHandle() { + deleteProc(); +} + +bool BaseProcHandle::isProcReady() const { + return mUnit && mUnit->isReady(); +} + +bool BaseProcHandle::hasProcCreationFailed() const { + if (mFailed) + return true; + + if (!mUnit) + return false; + + const auto status = mUnit->getStatus(); + if (status == BaseProcUnit::Status::NoProc || status == BaseProcUnit::Status::Cancelled) + return true; + + if (mUnit->getCreateTask().getStatus() == util::Task::Status::RemovedFromQueue || + status == BaseProcUnit::Status::Cancelled) { + return true; + } + + return false; +} + +bool BaseProcHandle::isProcCreationCancelled() const { + if (!mUnit) + return false; + + if (mUnit->getCreateTask().getStatus() == util::Task::Status::RemovedFromQueue) + return true; + + if (mUnit->getStatus() == BaseProcUnit::Status::Cancelled) + return true; + + return false; +} + +void BaseProcHandle::deleteProcIfFailed() { + if (mFailed && !mUnit) { + mFailed = false; + return; + } + + if (hasProcCreationFailed()) + deleteProc(); +} + +void BaseProcHandle::deleteProc() { if (mUnit) { mUnit->deleteProc(0, this); mUnit = nullptr; } - mFlag = 0; -} - -bool BaseProcHandle::procReady() { - return mUnit && mUnit->isReady(); + mFailed = false; } -BaseProc* BaseProcHandle::getProc() { +BaseProc* BaseProcHandle::getProc() const { if (mUnit) return mUnit->getProc(); return nullptr; } +BaseProc* BaseProcHandle::releaseProc() { + if (!isProcReady()) + return nullptr; + + BaseProcUnit* unit = mUnit; + BaseProc* proc = nullptr; + + { + ActorLinkConstDataAccess accessor; + { + const auto lock = sead::makeScopedLock(unit->getCS()); + if (unit->compareExchangeHandle(this, &gDummyProcHandle)) { + if (unit->getProc()) + accessor.acquire(unit->getProc()); + } + } + + proc = accessor.mProc; + if (proc) + proc->requestDeleteProcUnit(); + } + + mUnit = nullptr; + return proc; +} + +BaseProc* BaseProcHandle::releaseAndWakeProc() { + if (!isProcReady()) + return nullptr; + + BaseProcUnit* unit = mUnit; + BaseProc* proc = nullptr; + + { + ActorLinkConstDataAccess accessor; + { + const auto lock = sead::makeScopedLock(unit->getCS()); + if (unit->compareExchangeHandle(this, &gDummyProcHandle)) { + if (unit->getProc()) + accessor.acquire(unit->getProc()); + } + } + + proc = accessor.mProc; + if (proc) + proc->wakeUp(BaseProc::SleepWakeReason::_0); + } + + mUnit = nullptr; + return proc; +} + +BaseProcCreateTask* BaseProcHandle::getCreateTask() const { + sead::Atomic<BaseProcUnit*> unit = mUnit; + auto* ret = unit ? &unit->getCreateTask() : nullptr; + static_cast<void>(unit.load()); + return ret; +} + +bool BaseProcHandle::allocUnit() { + if (mUnit) + return false; + + int idx = gUnitPool.idx; + for (int i = 0; i < gUnitPool.units.size(); ++idx, ++i) { + idx = (idx == gUnitPool.units.size()) ? 0 : idx; + auto* unit = gUnitPool.get(idx); + + if (!unit->getCreateTask().canSubmitRequest()) + continue; + if (unit->getProc() != nullptr) + continue; + if (!unit->compareExchangeHandle(nullptr, this)) + continue; + + gUnitPool.idx = idx + 1; + mUnit = unit; + if (!mUnit) + return false; + + mUnit->setInitializingStatus(); + return true; + } + + mUnit = nullptr; + return false; +} + } // namespace ksys::act |
