summaryrefslogtreecommitdiff
path: root/src
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
parente36bc464b6fb19e80a1755b469b8a29295d080cc (diff)
ksys/act: Finish BaseProcHandle
Diffstat (limited to 'src')
-rw-r--r--src/KingSystem/ActorSystem/actActorLinkConstDataAccess.h1
-rw-r--r--src/KingSystem/ActorSystem/actBaseProc.h6
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcHandle.cpp154
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcHandle.h23
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcInitializer.cpp6
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcUnit.cpp30
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcUnit.h52
7 files changed, 229 insertions, 43 deletions
diff --git a/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.h b/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.h
index c608f9ba..18d2a4b4 100644
--- a/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.h
+++ b/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.h
@@ -39,6 +39,7 @@ public:
protected:
friend class ActorConstDataAccess;
friend class BaseProc;
+ friend class BaseProcHandle;
friend class BaseProcUnit;
bool mAcquired = false;
diff --git a/src/KingSystem/ActorSystem/actBaseProc.h b/src/KingSystem/ActorSystem/actBaseProc.h
index 9df6427b..c2712ed7 100644
--- a/src/KingSystem/ActorSystem/actBaseProc.h
+++ b/src/KingSystem/ActorSystem/actBaseProc.h
@@ -4,6 +4,7 @@
#include <container/seadListImpl.h>
#include <container/seadSafeArray.h>
#include <container/seadTreeMap.h>
+#include <math/seadMathCalcCommon.h>
#include <prim/seadBitFlag.h>
#include <prim/seadRuntimeTypeInfo.h>
#include <prim/seadSafeString.h>
@@ -122,7 +123,6 @@ public:
void setCreatePriorityState1();
void setCreatePriorityState2();
- bool setStateFlag(u32 flag_bit);
void onJobPush(JobType type) {
onJobPush1_(type);
@@ -135,6 +135,7 @@ public:
/// Set the BaseProcUnit. Only for use by BaseProcCreateTask.
void setUnitForBaseProcCreateTask(BaseProcUnit* unit) { mProcUnit = unit; }
void setInitializedFlag() { mFlags.set(Flags::Initialized); }
+ bool requestDeleteProcUnit() { return setStateFlag(StateFlags::RequestDeleteProcUnit); }
protected:
friend class BaseProcLinkDataMgr;
@@ -279,6 +280,9 @@ protected:
BaseProcJobHandler*& getJobHandler(JobType type) { return mJobHandlers[int(type)]; }
BaseProcJobHandler* getJobHandler(JobType type) const { return mJobHandlers[int(type)]; }
+ bool setStateFlag(u32 flag_bit);
+ bool setStateFlag(StateFlags flag) { return setStateFlag(sead::log2(u32(flag))); }
+
bool x00000071011ba9fc();
sead::FixedSafeString<64> mName;
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
diff --git a/src/KingSystem/ActorSystem/actBaseProcHandle.h b/src/KingSystem/ActorSystem/actBaseProcHandle.h
index a9815995..7a28f949 100644
--- a/src/KingSystem/ActorSystem/actBaseProcHandle.h
+++ b/src/KingSystem/ActorSystem/actBaseProcHandle.h
@@ -14,21 +14,26 @@ public:
BaseProcHandle();
~BaseProcHandle();
- bool procReady();
+ bool isProcReady() const;
+ bool hasProcCreationFailed() const;
+ bool isProcCreationCancelled() const;
- BaseProc* getProc();
+ void deleteProcIfFailed();
+ void deleteProc();
+
+ BaseProc* getProc() const;
+ BaseProc* releaseProc();
+ BaseProc* releaseAndWakeProc();
+ BaseProcCreateTask* getCreateTask() const;
BaseProcUnit* getUnit() const { return mUnit; }
bool allocUnit();
- BaseProcCreateTask* getCreateTask() const;
-
- bool getFlag() const { return mFlag; }
- void setFlag(bool flag) { mFlag = flag; }
- static BaseProcHandle sDummyHandle;
+ bool hasFailed() const { return mFailed; }
+ void setFailed(bool failed) { mFailed = failed; }
private:
- BaseProcUnit* mUnit;
- bool mFlag;
+ BaseProcUnit* mUnit = nullptr;
+ bool mFailed = false;
};
KSYS_CHECK_SIZE_NX150(BaseProcHandle, 0x10);
diff --git a/src/KingSystem/ActorSystem/actBaseProcInitializer.cpp b/src/KingSystem/ActorSystem/actBaseProcInitializer.cpp
index da1c33f1..2785fd5b 100644
--- a/src/KingSystem/ActorSystem/actBaseProcInitializer.cpp
+++ b/src/KingSystem/ActorSystem/actBaseProcInitializer.cpp
@@ -89,7 +89,7 @@ void BaseProcInitializer::deleteThreadIfPaused() {
bool BaseProcInitializer::requestCreateBaseProc(const BaseProcCreateRequest& req) {
if (!mActorGenerationEnabled) {
if (req.task_data->mProcHandle)
- req.task_data->mProcHandle->setFlag(true);
+ req.task_data->mProcHandle->setFailed(true);
return false;
}
@@ -112,13 +112,13 @@ bool BaseProcInitializer::requestCreateBaseProc(const BaseProcCreateRequest& req
util::TaskMgrRequest mgr_req;
if (req.task_data->mProcHandle) {
if (!req.task_data->mProcHandle->allocUnit()) {
- req.task_data->mProcHandle->setFlag(true);
+ req.task_data->mProcHandle->setFailed(true);
return false;
}
mgr_req.task = req.task_data->mProcHandle->getCreateTask();
if (!mgr_req.task) {
- req.task_data->mProcHandle->setFlag(true);
+ req.task_data->mProcHandle->setFailed(true);
return false;
}
} else {
diff --git a/src/KingSystem/ActorSystem/actBaseProcUnit.cpp b/src/KingSystem/ActorSystem/actBaseProcUnit.cpp
index cac5c864..23baa4ea 100644
--- a/src/KingSystem/ActorSystem/actBaseProcUnit.cpp
+++ b/src/KingSystem/ActorSystem/actBaseProcUnit.cpp
@@ -8,7 +8,19 @@
namespace ksys::act {
-bool BaseProcUnit::deleteProc(u32, BaseProcHandle* handle) {
+BaseProcUnitPool gUnitPool{};
+BaseProcHandle gDummyProcHandle;
+
+BaseProcUnit::~BaseProcUnit() {
+ deleteProc(0, nullptr);
+}
+
+bool BaseProcUnit::deleteProc([[maybe_unused]] u32 x, BaseProcHandle* handle) {
+#ifdef MATCHING_HACK_NX_CLANG
+ // Ensure x is not optimized out.
+ __builtin_assume(x);
+#endif
+
ActorLinkConstDataAccess accessor;
{
@@ -18,8 +30,8 @@ bool BaseProcUnit::deleteProc(u32, BaseProcHandle* handle) {
if (mProc)
accessor.acquire(mProc);
- if (mStatus == Status::_1 || mProc) {
- mHandle.compareExchange(handle, &BaseProcHandle::sDummyHandle);
+ if (mStatus == Status::Initializing || mProc) {
+ mHandle.compareExchange(handle, &gDummyProcHandle);
} else {
mStatus = Status::Unused;
mHandle = nullptr;
@@ -65,7 +77,7 @@ bool BaseProcUnit::setProc(BaseProc* proc) {
return false;
}
- if (mStatus != Status::_1)
+ if (mStatus != Status::Initializing)
print_info();
mProc = proc;
@@ -75,7 +87,7 @@ bool BaseProcUnit::setProc(BaseProc* proc) {
void BaseProcUnit::reset() {
auto* handle = getHandle();
- if (handle != &BaseProcHandle::sDummyHandle) {
+ if (handle != &gDummyProcHandle) {
sead::FixedSafeString<256> message;
message.format("BaseProcUnit:%p, %p", this, handle);
util::PrintDebug(message);
@@ -85,7 +97,7 @@ void BaseProcUnit::reset() {
mHandle = nullptr;
}
-void BaseProcUnit::cleanUp(BaseProc* proc, bool set_status_5) {
+void BaseProcUnit::cleanUp(BaseProc* proc, bool is_cancellation) {
const auto lock = sead::makeScopedLock(mCS);
mProc = nullptr;
@@ -102,9 +114,9 @@ void BaseProcUnit::cleanUp(BaseProc* proc, bool set_status_5) {
print_info();
} else {
const auto status = mStatus.load();
- if (status == Status::Unused || (status > Status::_3 && status != Status::_5))
+ if (status == Status::Unused || (status > Status::NoProc && status != Status::Cancelled))
print_info();
- mStatus = set_status_5 ? Status::_5 : Status::_3;
+ mStatus = is_cancellation ? Status::Cancelled : Status::NoProc;
}
}
@@ -123,7 +135,7 @@ void BaseProcUnit::unlinkProc(BaseProc* proc) {
}
bool BaseProcUnit::isParentHandleDefault() const {
- return mHandle == &BaseProcHandle::sDummyHandle;
+ return mHandle == &gDummyProcHandle;
}
} // namespace ksys::act
diff --git a/src/KingSystem/ActorSystem/actBaseProcUnit.h b/src/KingSystem/ActorSystem/actBaseProcUnit.h
index 20309485..07ccbabb 100644
--- a/src/KingSystem/ActorSystem/actBaseProcUnit.h
+++ b/src/KingSystem/ActorSystem/actBaseProcUnit.h
@@ -1,6 +1,7 @@
#pragma once
#include <basis/seadTypes.h>
+#include <container/seadSafeArray.h>
#include <thread/seadAtomic.h>
#include <thread/seadCriticalSection.h>
#include "KingSystem/ActorSystem/actBaseProcCreateTask.h"
@@ -12,25 +13,44 @@ class BaseProcHandle;
class BaseProcUnit {
public:
+ enum class Status : u32 {
+ Unused = 0,
+ Initializing = 1,
+ Ready = 2,
+ NoProc = 3,
+ _4 = 4,
+ Cancelled = 5,
+ };
+
+ BaseProcUnit() = default;
+ ~BaseProcUnit();
+
+ BaseProcUnit(const BaseProcUnit&) = delete;
+ BaseProcUnit(BaseProcUnit&&) = delete;
+ auto operator=(const BaseProcUnit&) = delete;
+ auto operator=(BaseProcUnit&&) = delete;
+
bool deleteProc(u32, BaseProcHandle* handle);
bool setProc(BaseProc* proc);
void unlinkProc(BaseProc* proc);
- void cleanUp(BaseProc* proc, bool set_status_5);
+ void cleanUp(BaseProc* proc, bool is_cancellation);
bool isParentHandleDefault() const;
+ Status getStatus() const { return mStatus; }
BaseProc* getProc() const { return mProc; }
+ BaseProcCreateTask& getCreateTask() { return mCreateTask; }
+ const BaseProcCreateTask& getCreateTask() const { return mCreateTask; }
+ sead::CriticalSection& getCS() { return mCS; }
+
bool isReady() const { return mStatus == Status::Ready; }
-private:
- enum class Status : u32 {
- Unused = 0,
- _1 = 1,
- Ready = 2,
- _3 = 3,
- _4 = 4,
- _5 = 5,
- };
+ bool compareExchangeHandle(BaseProcHandle* expected, BaseProcHandle* desired) {
+ return mHandle.compareExchange(expected, desired);
+ }
+
+ void setInitializingStatus() { mStatus = Status::Initializing; }
+private:
void reset();
BaseProcHandle* getHandle() const { return mHandle.load(); }
@@ -38,9 +58,19 @@ private:
sead::Atomic<Status> mStatus = Status::Unused;
sead::Atomic<BaseProcHandle*> mHandle{};
BaseProc* mProc{};
- BaseProcCreateTask mCreateTask;
+ BaseProcCreateTask mCreateTask{nullptr};
sead::CriticalSection mCS;
};
KSYS_CHECK_SIZE_NX150(BaseProcUnit, 0x2f0);
+struct BaseProcUnitPool {
+ BaseProcUnit* get(int i) { return &units[i]; }
+
+ sead::SafeArray<BaseProcUnit, 256> units;
+ int idx = 0;
+};
+
+extern BaseProcUnitPool gUnitPool;
+extern BaseProcHandle gDummyProcHandle;
+
} // namespace ksys::act