• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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