1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "entity_manager.h"
17
18 #include <algorithm>
19 #include <atomic>
20
21 #include <core/log.h>
22 #include <core/namespace.h>
23
24 CORE_BEGIN_NAMESPACE()
25 using BASE_NS::pair;
26 using BASE_NS::vector;
27
28 namespace {
GetId(const Entity & e)29 uint32_t GetId(const Entity& e)
30 {
31 return e.id & 0xFFFFFFFF;
32 }
33
GetGeneration(const Entity & e)34 uint32_t GetGeneration(const Entity& e)
35 {
36 return (e.id >> 32l) & 0xFFFFFFFF;
37 }
38
MakeEntityId(uint32_t g,uint32_t i)39 Entity MakeEntityId(uint32_t g, uint32_t i)
40 {
41 return { (static_cast<uint64_t>(g) << 32l) | i };
42 }
43 class EntityReferenceCounter final : public IEntityReferenceCounter {
44 public:
45 using Ptr = BASE_NS::refcnt_ptr<EntityReferenceCounter>;
46 EntityReferenceCounter() = default;
47 ~EntityReferenceCounter() override = default;
48
49 protected:
Ref()50 void Ref() noexcept override
51 {
52 refcnt_.fetch_add(1, std::memory_order_relaxed);
53 }
54
Unref()55 void Unref() noexcept override
56 {
57 if (std::atomic_fetch_sub_explicit(&refcnt_, 1, std::memory_order_release) == 0) {
58 std::atomic_thread_fence(std::memory_order_acquire);
59 delete this;
60 }
61 }
62
GetRefCount() const63 int32_t GetRefCount() const noexcept override
64 {
65 return refcnt_.load();
66 }
67
68 private:
69 std::atomic<int32_t> refcnt_ { -1 };
70 };
71 } // namespace
72
EntityManager()73 EntityManager::EntityManager() : EntityManager((const size_t)64) {}
74
EntityManager(const size_t entityCount)75 EntityManager::EntityManager(const size_t entityCount)
76 {
77 entities_.reserve(entityCount);
78 }
79
~EntityManager()80 EntityManager::~EntityManager()
81 {
82 // count live entities, should be zero
83 int32_t liveEntities = 0;
84 int32_t inactiveEntities = 0;
85 for (const auto& e : entities_) {
86 if (EntityState::State::ALIVE == e.state) {
87 ++liveEntities;
88 }
89 if (EntityState::State::INACTIVE == e.state) {
90 ++inactiveEntities;
91 }
92 }
93 CORE_ASSERT(inactiveEntities == 0);
94 CORE_ASSERT(liveEntities == 0);
95 }
96
Create()97 Entity EntityManager::Create()
98 {
99 // find first free, dead, or with zero refcnt.
100 auto it = std::find_if(entities_.begin(), entities_.end(), [](const auto& b) {
101 return (b.state == EntityState::State::FREE) || (b.state == EntityState::State::DEAD) ||
102 (b.counter && (b.counter->GetRefCount() == 0));
103 });
104 Entity result;
105 if (it == entities_.end()) {
106 const auto generation = 1U;
107 const auto id = (uint32_t)entities_.size();
108 entities_.push_back({ EntityState::State::ALIVE, generation, nullptr });
109 result = MakeEntityId(generation, id);
110 } else {
111 const auto id = (uint32_t)(it - entities_.begin());
112 auto& slot = *it;
113 // if the slot isn't free report a dead entity
114 if (slot.state != EntityState::State::FREE) {
115 const auto deadEntity = MakeEntityId(slot.generation, id);
116 removedList_.push_back(deadEntity);
117 eventList_.push_back({ deadEntity, EventType::DESTROYED });
118 }
119 slot.counter = nullptr; // NOTE: could push to a pool and recycle used often
120 ++slot.generation;
121
122 slot.state = EntityState::State::ALIVE;
123 result = MakeEntityId(slot.generation, id);
124 }
125 addedList_.push_back(result);
126 eventList_.push_back({ result, EventType::CREATED });
127 ++generationCounter_;
128 return result;
129 }
130
CreateReferenceCounted()131 EntityReference EntityManager::CreateReferenceCounted()
132 {
133 // find first free or dead.
134 auto it = std::find_if(entities_.begin(), entities_.end(), [](const auto& b) {
135 return (b.state == EntityState::State::FREE) || (b.state == EntityState::State::DEAD) ||
136 (b.counter && (b.counter->GetRefCount() == 0));
137 });
138 Entity result;
139 if (it == entities_.end()) {
140 const auto generation = 1U;
141 const auto id = (uint32_t)entities_.size();
142 entities_.push_back(
143 { EntityState::State::ALIVE, generation, IEntityReferenceCounter::Ptr { new EntityReferenceCounter } });
144 result = MakeEntityId(generation, id);
145 } else {
146 const auto id = (uint32_t)(it - entities_.begin());
147 auto& slot = *it;
148 // if the slot isn't free report a dead entity
149 if (slot.state != EntityState::State::FREE) {
150 const auto deadEntity = MakeEntityId(slot.generation, id);
151 removedList_.push_back(deadEntity);
152 eventList_.push_back({ deadEntity, EventType::DESTROYED });
153 }
154 if (!slot.counter) {
155 slot.counter.reset(new EntityReferenceCounter);
156 }
157 ++slot.generation;
158 slot.state = EntityState::State::ALIVE;
159 result = MakeEntityId(slot.generation, id);
160 }
161 addedList_.push_back(result);
162 eventList_.push_back({ result, EventType::CREATED });
163 ++generationCounter_;
164 return EntityReference(result, entities_[GetId(result)].counter);
165 }
166
GetReferenceCounted(const Entity entity)167 EntityReference EntityManager::GetReferenceCounted(const Entity entity)
168 {
169 if (EntityUtil::IsValid(entity)) {
170 if (const uint32_t id = GetId(entity); id < entities_.size()) {
171 auto& e = entities_[id];
172 // make sure the given entity id has the same generation and that the entity isn't dead or free.
173 if ((e.generation == GetGeneration(entity)) &&
174 ((e.state == EntityState::State::ALIVE) || (e.state == EntityState::State::INACTIVE))) {
175 if (!e.counter) {
176 // entity wasn't yet reference counted so add a counter
177 e.counter.reset(new EntityReferenceCounter);
178 return { entity, e.counter };
179 } else if (e.counter->GetRefCount() > 0) {
180 // reference count is still valid
181 return { entity, e.counter };
182 } else {
183 // reference count has expired, but we won't revive the entity.
184 }
185 }
186 }
187 }
188 return {};
189 }
190
Destroy(const Entity entity)191 void EntityManager::Destroy(const Entity entity)
192 {
193 if (EntityUtil::IsValid(entity)) {
194 if (const uint32_t id = GetId(entity); id < entities_.size()) {
195 auto& e = entities_[id];
196 if ((e.generation == GetGeneration(entity)) &&
197 ((e.state == EntityState::State::ALIVE) || (e.state == EntityState::State::INACTIVE))) {
198 e.state = EntityState::State::DEAD;
199 e.counter = nullptr;
200 removedList_.push_back(entity);
201 eventList_.push_back({ entity, EventType::DESTROYED });
202 ++generationCounter_;
203 }
204 }
205 }
206 }
207
DestroyAllEntities()208 void EntityManager::DestroyAllEntities()
209 {
210 for (uint32_t i = 0; i < (uint32_t)entities_.size(); ++i) {
211 auto& e = entities_[i];
212 if ((EntityState::State::ALIVE == e.state) || (EntityState::State::INACTIVE == e.state)) {
213 auto entity = MakeEntityId(e.generation, i);
214 removedList_.push_back(entity);
215 eventList_.push_back({ entity, EventType::DESTROYED });
216 e.counter = nullptr;
217 e.state = EntityState::State::DEAD;
218 }
219 }
220 ++generationCounter_;
221 }
222
IsAlive(const Entity entity) const223 bool EntityManager::IsAlive(const Entity entity) const
224 {
225 if (EntityUtil::IsValid(entity)) {
226 const uint32_t id = GetId(entity);
227 if (id < entities_.size()) {
228 const auto& state = entities_[id];
229 if (state.generation == GetGeneration(entity)) {
230 return (state.state == EntityState::State::ALIVE) &&
231 (!state.counter || (state.counter->GetRefCount() > 0));
232 }
233 }
234 }
235 return false;
236 }
237
GetAddedEntities()238 vector<Entity> EntityManager::GetAddedEntities()
239 {
240 return move(addedList_);
241 }
242
GetRemovedEntities()243 vector<Entity> EntityManager::GetRemovedEntities()
244 {
245 for (const Entity& e : removedList_) {
246 const uint32_t id = GetId(e);
247 if (id < entities_.size()) {
248 if (entities_[id].generation == GetGeneration(e)) {
249 CORE_ASSERT(entities_[id].state == EntityState::State::DEAD);
250 if (id < entities_.size() - 1) {
251 entities_[id].state = EntityState::State::FREE;
252 } else {
253 entities_.resize(entities_.size() - 1);
254 }
255 }
256 }
257 }
258 return move(removedList_);
259 }
260
GetGenerationCounter() const261 uint32_t EntityManager::GetGenerationCounter() const
262 {
263 return generationCounter_;
264 }
265
GetEvents()266 vector<pair<Entity, IEntityManager::EventType>> EntityManager::GetEvents()
267 {
268 return move(eventList_);
269 }
270
SetActive(const Entity entity,bool state)271 void EntityManager::SetActive(const Entity entity, bool state)
272 {
273 if (EntityUtil::IsValid(entity)) {
274 EntityState::State oldState, newState;
275 EventType event;
276 if (state == true) {
277 oldState = EntityState::State::INACTIVE;
278 newState = EntityState::State::ALIVE;
279 event = EventType::ACTIVATED;
280 } else {
281 oldState = EntityState::State::ALIVE;
282 newState = EntityState::State::INACTIVE;
283 event = EventType::DEACTIVATED;
284 }
285
286 uint32_t id = GetId(entity);
287 if (id < entities_.size()) {
288 if (entities_[id].generation == GetGeneration(entity)) {
289 if (entities_[id].state == oldState) {
290 entities_[id].state = newState;
291 eventList_.push_back({ entity, event });
292 ++generationCounter_;
293 }
294 }
295 }
296 }
297 }
298
UpdateDeadEntities()299 void EntityManager::UpdateDeadEntities()
300 {
301 const auto removedCount = removedList_.size();
302 for (uint32_t id = 0, count = (uint32_t)entities_.size(); id < count; ++id) {
303 auto& e = entities_[id];
304 if ((e.state != EntityState::State::FREE) && e.counter && (e.counter->GetRefCount() == 0)) {
305 const Entity entity = MakeEntityId(e.generation, id);
306 removedList_.push_back(entity);
307 eventList_.push_back({ entity, EventType::DESTROYED });
308 e.state = EntityState::State::DEAD;
309 }
310 }
311 if (removedCount != removedList_.size()) {
312 ++generationCounter_;
313 }
314 }
315
IteratorImpl(const EntityManager & owner,size_t index,IteratorType type)316 EntityManager::IteratorImpl::IteratorImpl(const EntityManager& owner, size_t index, IteratorType type)
317 : owner_(&owner), index_(static_cast<uint32_t>(index)), type_(type)
318 {
319 const auto valid = (type == IteratorType::DEACTIVATED) ? EntityState::State::INACTIVE : EntityState::State::ALIVE;
320 if (index < owner.entities_.size()) {
321 const auto& e = owner.entities_[index];
322 if ((e.state != valid) || (e.counter && e.counter->GetRefCount() == 0)) {
323 Next();
324 }
325 }
326 }
327
GetOwner() const328 const class IEntityManager* EntityManager::IteratorImpl::GetOwner() const
329 {
330 return owner_;
331 }
332
Compare(const Iterator::Ptr & other) const333 bool EntityManager::IteratorImpl::Compare(const Iterator::Ptr& other) const
334 {
335 if ((other == nullptr) || (other->GetOwner() != owner_)) {
336 return false;
337 }
338 auto* otheri = static_cast<const EntityManager::IteratorImpl*>(other.get());
339 return (index_ == otheri->index_) && (type_ == otheri->type_);
340 }
341
Next()342 bool EntityManager::IteratorImpl::Next()
343 {
344 const auto& entities = owner_->entities_;
345 if (index_ < entities.size()) {
346 const auto valid =
347 (type_ == IteratorType::DEACTIVATED) ? EntityState::State::INACTIVE : EntityState::State::ALIVE;
348
349 ++index_;
350 while (index_ < entities.size()) {
351 auto& state = entities[index_];
352 if ((state.state == valid) && ((!state.counter) || (state.counter->GetRefCount() > 0))) {
353 break;
354 }
355 ++index_;
356 }
357 }
358 return (index_ < owner_->entities_.size());
359 }
360
Get() const361 Entity EntityManager::IteratorImpl::Get() const
362 {
363 if (index_ >= owner_->entities_.size()) {
364 return {};
365 }
366 return MakeEntityId(owner_->entities_[index_].generation, index_);
367 }
368
MakeIterator(uint32_t index,IteratorType type) const369 IEntityManager::Iterator::Ptr EntityManager::MakeIterator(uint32_t index, IteratorType type) const
370 {
371 auto del = [](Iterator* it) { delete (EntityManager::IteratorImpl*)(it); };
372 auto p = new EntityManager::IteratorImpl(*this, index, type);
373 return { p, del };
374 }
375
Clone() const376 IEntityManager::Iterator::Ptr EntityManager::IteratorImpl::Clone() const
377 {
378 return owner_->MakeIterator(index_, type_);
379 }
380
Begin(IteratorType type) const381 IEntityManager::Iterator::Ptr EntityManager::Begin(IteratorType type) const
382 {
383 return MakeIterator(0U, type);
384 }
385
End(IteratorType type) const386 IEntityManager::Iterator::Ptr EntityManager::End(IteratorType type) const
387 {
388 return MakeIterator(static_cast<uint32_t>(entities_.size()), type);
389 }
390
391 CORE_END_NAMESPACE()
392