summaryrefslogtreecommitdiff
path: root/src/KingSystem/ActorSystem/actActorLimiter.cpp
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2020-12-31 17:56:31 +0100
committerLéo Lam <leo@leolam.fr>2021-01-01 12:52:58 +0100
commit3f9172043ca4af76940e72653193c0948ffcc192 (patch)
tree33d03e505c330c940200a6f5648c3a3a910b93a8 /src/KingSystem/ActorSystem/actActorLimiter.cpp
parent1f12ab92375bf5400270258247d3a6abb44d1e46 (diff)
ksys: Implement ActorLimiter
Diffstat (limited to 'src/KingSystem/ActorSystem/actActorLimiter.cpp')
-rw-r--r--src/KingSystem/ActorSystem/actActorLimiter.cpp71
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