mirror of
https://github.com/zeldaret/botw
synced 2026-06-01 17:57:31 -04:00
ksys/act: Implement BaseProcLink
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user