diff options
| author | Léo Lam <leo@leolam.fr> | 2020-12-31 17:56:31 +0100 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2021-01-01 12:52:58 +0100 |
| commit | 3f9172043ca4af76940e72653193c0948ffcc192 (patch) | |
| tree | 33d03e505c330c940200a6f5648c3a3a910b93a8 /src/KingSystem/ActorSystem/actActorLimiter.cpp | |
| parent | 1f12ab92375bf5400270258247d3a6abb44d1e46 (diff) | |
ksys: Implement ActorLimiter
Diffstat (limited to 'src/KingSystem/ActorSystem/actActorLimiter.cpp')
| -rw-r--r-- | src/KingSystem/ActorSystem/actActorLimiter.cpp | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/KingSystem/ActorSystem/actActorLimiter.cpp b/src/KingSystem/ActorSystem/actActorLimiter.cpp new file mode 100644 index 00000000..08925e8a --- /dev/null +++ b/src/KingSystem/ActorSystem/actActorLimiter.cpp @@ -0,0 +1,71 @@ +#include "KingSystem/ActorSystem/actActorLimiter.h" +#include "KingSystem/ActorSystem/actActorConstDataAccess.h" +#include "KingSystem/ActorSystem/actTag.h" + +namespace ksys::act { + +bool ActorLimiter::List::init(sead::Heap* heap, int capacity) { + mNodes.allocBufferAssert(capacity, heap); + if (!mNodes.isBufferReady()) + return false; + + for (auto& node : mNodes) + mActorList.pushBack(&node); + + return true; +} + +bool ActorLimiter::List::addActor(BaseProc* proc, bool allow_evicting_old_actors) { + const auto lock = sead::makeScopedLock(mCritSection); + + // Find a free node. + Node* target_node = nullptr; + for (auto& node : mActorList) { + if (node.proc_link.hasProc()) + continue; + + mActorList.erase(&node); + target_node = &node; + break; + } + + if (target_node == nullptr) { + if (!allow_evicting_old_actors) + return false; + + target_node = mActorList.popFront(); + if (target_node) { + ActorConstDataAccess acc; + acquireActor(&target_node->proc_link, &acc); + + // Priority material actors will not be evicted if possible. + if (acc.hasTag(tags::PriorityMaterial)) { + mActorList.pushBack(target_node); + target_node = mActorList.popFront(); + if (target_node) + acquireActor(&target_node->proc_link, &acc); + } + + acc.fadeOutDelete(BaseProc::DeleteReason::_15); + } + + if (target_node == nullptr) + return false; + } + + target_node->proc_link.acquire(proc, false); + mActorList.pushBack(target_node); + return true; +} + +SEAD_SINGLETON_DISPOSER_IMPL(ActorLimiter) + +bool ActorLimiter::init(sead::Heap* heap, const sead::SafeArray<int, NumCategories>& capacities) { + for (s32 i = 0; i < NumCategories; ++i) { + if (!mLists.ref()[i].init(heap, capacities[i])) + return false; + } + return true; +} + +} // namespace ksys::act |
