summaryrefslogtreecommitdiff
path: root/src/KingSystem/ActorSystem/actBaseProcHandle.cpp
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2021-03-14 14:05:38 +0100
committerLéo Lam <leo@leolam.fr>2021-03-14 17:11:38 +0100
commit4f2c0a60798d07bc77121e4ef02fbf17075c52da (patch)
tree8e6da2b84da5ea999480c00d32167f254150cdc2 /src/KingSystem/ActorSystem/actBaseProcHandle.cpp
parente36bc464b6fb19e80a1755b469b8a29295d080cc (diff)
ksys/act: Finish BaseProcHandle
Diffstat (limited to 'src/KingSystem/ActorSystem/actBaseProcHandle.cpp')
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcHandle.cpp154
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