blob: 94531c96d00d9ae5525338bf983011a7265a71e0 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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.deleteEx(BaseProc::DeleteReason::_f);
}
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[i].init(heap, capacities[i]))
return false;
}
return true;
}
} // namespace ksys::act
|