diff options
| author | Léo Lam <leo@leolam.fr> | 2020-08-20 13:15:12 +0200 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2020-08-20 18:25:47 +0200 |
| commit | afde5b27753162e187cffc6ec765099bd0767459 (patch) | |
| tree | 88b6ed4fb1ab57d556b653840b6969eb987d9d8e /src/KingSystem/ActorSystem/actBaseProcLink.cpp | |
| parent | f92ab2f5598789d9531bfe93e9abcc3dc4cc938d (diff) | |
ksys/act: Implement BaseProcLink
Diffstat (limited to 'src/KingSystem/ActorSystem/actBaseProcLink.cpp')
| -rw-r--r-- | src/KingSystem/ActorSystem/actBaseProcLink.cpp | 160 |
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 |
