summaryrefslogtreecommitdiff
path: root/src/KingSystem/ActorSystem/actBaseProcLink.cpp
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2020-08-20 13:15:12 +0200
committerLéo Lam <leo@leolam.fr>2020-08-20 18:25:47 +0200
commitafde5b27753162e187cffc6ec765099bd0767459 (patch)
tree88b6ed4fb1ab57d556b653840b6969eb987d9d8e /src/KingSystem/ActorSystem/actBaseProcLink.cpp
parentf92ab2f5598789d9531bfe93e9abcc3dc4cc938d (diff)
ksys/act: Implement BaseProcLink
Diffstat (limited to 'src/KingSystem/ActorSystem/actBaseProcLink.cpp')
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcLink.cpp160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/KingSystem/ActorSystem/actBaseProcLink.cpp b/src/KingSystem/ActorSystem/actBaseProcLink.cpp
new file mode 100644
index 00000000..a99960d9
--- /dev/null
+++ b/src/KingSystem/ActorSystem/actBaseProcLink.cpp
@@ -0,0 +1,160 @@
+#include "KingSystem/ActorSystem/actBaseProcLink.h"
+#include <prim/seadScopedLock.h>
+#include <thread/seadThread.h>
+#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h"
+#include "KingSystem/ActorSystem/actBaseProc.h"
+#include "KingSystem/ActorSystem/actBaseProcMgr.h"
+
+namespace ksys::act {
+
+BaseProcLink::BaseProcLink() = default;
+
+BaseProcLink& BaseProcLink::operator=(const BaseProcLink& rhs) {
+ if (this == &rhs)
+ return *this;
+
+ reset();
+
+ if (rhs.mData)
+ mData = rhs.mData;
+ mId = rhs.mId;
+
+ return *this;
+}
+
+bool BaseProcLink::operator==(const BaseProcLink& rhs) const {
+ return (!hasProc() && !rhs.hasProc()) || mId == rhs.mId;
+}
+
+bool BaseProcLink::hasProc() const {
+ return getProc();
+}
+
+bool BaseProcLink::hasProcInCalcState() const {
+ return getProcInContext(
+ [](BaseProc* proc) { return proc && proc->getState() == BaseProc::State::Calc; });
+}
+
+bool BaseProcLink::hasProcById(BaseProc* proc) const {
+ return proc != nullptr & mId != cInvalidId && mId == proc->getId();
+}
+
+BaseProc* BaseProcLink::getProc(ActorLinkConstDataAccess* accessor, BaseProc* other_proc) {
+ return getProcInContext([&](BaseProc* proc) -> BaseProc* {
+ if (proc && acquireProc(accessor, proc, "frm::BaseProcLink") &&
+ BaseProcMgr::instance()->isAccessingProcSafe(proc, other_proc)) {
+ return proc;
+ }
+ return nullptr;
+ });
+}
+
+BaseProc* BaseProcLink::getProc(ActorLinkConstDataAccess* accessor) {
+ return getProcInContext([&](BaseProc* proc) -> BaseProc* {
+ if (proc && acquireProc(accessor, proc, "frm::BaseProcLink"))
+ return proc;
+ return nullptr;
+ });
+}
+
+bool BaseProcLink::acquire(BaseProc* proc, bool acquire_immediately) {
+ reset();
+
+ if (!proc || proc->isDeletedOrDeleting())
+ return false;
+
+ mData = proc->getBaseProcLinkData();
+
+ if (!mData) {
+ static constexpr const char* sStateNames[] = {"Init", "Calc", "Sleep", "Delete"};
+ sead::FixedSafeString<256> message;
+ message.format("%s:%s", proc->getName().cstr(), sStateNames[u8(proc->getState())]);
+ return false;
+ }
+
+ mId = proc->getId();
+ if (acquire_immediately) {
+ mData->mRefCount.increment();
+ mAcquired = true;
+ }
+ return true;
+}
+
+void BaseProcLink::reset() {
+ if (mAcquired) {
+ mAcquired = false;
+ if (mData)
+ mData->mRefCount.decrement();
+ }
+ mId = cInvalidId;
+}
+
+bool BaseProcLink::isAccessingSpecifiedProcUnsafe(BaseProc* other) const {
+ return getProcInContext([&](BaseProc* proc) {
+ return proc && !BaseProcMgr::instance()->isAccessingProcSafe(proc, other);
+ });
+}
+
+SEAD_SINGLETON_DISPOSER_IMPL(BaseProcLinkDataMgr)
+
+BaseProc* BaseProcLinkData::getProc(u32 id, bool allow_deleted) const {
+ if (id == u32(-1) || mId != id)
+ return nullptr;
+
+ if (!allow_deleted && (!mProc || mProc->getState() == BaseProc::State::Delete))
+ return nullptr;
+
+ return mProc;
+}
+
+sead::CriticalSection* BaseProcLinkData::lockIfNeeded() {
+ if (BaseProcMgr::instance()->isHighPriorityThread())
+ return nullptr;
+
+ mCS.lock();
+ return &mCS;
+}
+
+bool BaseProcLinkDataMgr::acquireLink(BaseProc* proc) {
+ auto lock = sead::makeScopedLock(mCS);
+ s32 index = mIndex;
+ for (s32 i = 0; i < mData.size(); ++i) {
+ const s32 j = index == 0x800 ? 0 : index;
+ auto& data = mData[j];
+ if (data.mId == u32(-1)) {
+ {
+ auto data_lock = sead::makeScopedLock(data.mCS);
+ data.mProc = proc;
+ data.mId = proc->mId;
+ proc->mBaseProcLinkData = &data;
+ }
+ mIndex = j + 1;
+ return true;
+ }
+ index = j + 1;
+ }
+
+ for (s32 i = 0; i < mData.size(); ++i) {
+ auto data_lock = sead::makeScopedLock(mData[i].mCS);
+ // Debug code was probably here?
+ }
+
+ return false;
+}
+
+bool BaseProcLinkDataMgr::releaseLink(BaseProc* proc) {
+ auto* data = proc->mBaseProcLinkData;
+ if (!data)
+ return false;
+
+ const auto thread = sead::ThreadMgr::instance()->getCurrentThread();
+ thread->getPriority();
+
+ auto lock = sead::makeScopedLock(data->mCS);
+ data->mProc = nullptr;
+ data->mId = -1;
+ proc->mBaseProcLinkData = nullptr;
+ return true;
+}
+
+} // namespace ksys::act