1 // Copyright (C) 2019 The Android Open Source Project
2 //
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 #pragma once
15 
16 #include "aemu/base/containers/Lookup.h"
17 #include "aemu/base/Optional.h"
18 
19 #include <functional>
20 #include <unordered_map>
21 #include <vector>
22 
23 #include <inttypes.h>
24 #include <stdio.h>
25 
26 #define ENTITY_MANAGER_DEBUG 0
27 
28 #if ENTITY_MANAGER_DEBUG
29 
30 #define EM_DBG(fmt,...) fprintf(stderr, "%s:%d " fmt "\n", __func__, __LINE__, ##__VA_ARGS__);
31 
32 #else
33 #define EM_DBG(...)
34 #endif
35 
36 #define INVALID_ENTITY_HANDLE 0
37 #define INVALID_COMPONENT_HANDLE 0
38 
39 namespace android {
40 namespace base {
41 
42 // EntityManager: A way to represent an abstrat space of objects with handles.
43 // Each handle is associated with data of type Item for quick access from handles to data.
44 // Otherwise, entity data is spread through ComponentManagers.
45 template<size_t indexBits,
46          size_t generationBits,
47          size_t typeBits,
48          class Item>
49 class EntityManager {
50 public:
51 
52     static_assert(64 == (indexBits + generationBits + typeBits),
53                   "bits of index, generation, and type must add to 64");
54 
55     using EntityHandle = uint64_t;
56     using IteratorFunc = std::function<void(bool live, EntityHandle h, Item& item)>;
57     using ConstIteratorFunc = std::function<void(bool live, EntityHandle h, const Item& item)>;
58 
getHandleIndex(EntityHandle h)59     static size_t getHandleIndex(EntityHandle h) {
60         return static_cast<size_t>(h & ((1ULL << indexBits) - 1ULL));
61     }
62 
getHandleGeneration(EntityHandle h)63     static size_t getHandleGeneration(EntityHandle h) {
64         return static_cast<size_t>(
65             (h >> indexBits) &
66             ((1ULL << generationBits) - 1ULL));
67     }
68 
getHandleType(EntityHandle h)69     static size_t getHandleType(EntityHandle h) {
70         return static_cast<size_t>(
71             (h >> (indexBits + generationBits)) &
72             ((1ULL << typeBits) - 1ULL));
73         return h & ((1ULL << indexBits) - 1ULL);
74     }
75 
makeHandle(size_t index,size_t generation,size_t type)76     static EntityHandle makeHandle(
77         size_t index,
78         size_t generation,
79         size_t type) {
80         EntityHandle res = index;
81         res |= generation << indexBits;
82         res |= type << (indexBits + generationBits);
83         return res;
84     }
85 
withIndex(EntityHandle h,size_t i)86     static EntityHandle withIndex(EntityHandle h, size_t i) {
87         return makeHandle(i, getHandleGeneration(h), getHandleType(h));
88     }
89 
withGeneration(EntityHandle h,size_t nextGen)90     static EntityHandle withGeneration(EntityHandle h, size_t nextGen) {
91         return makeHandle(getHandleIndex(h), nextGen, getHandleType(h));
92     }
93 
withType(EntityHandle h,size_t newType)94     static EntityHandle withType(EntityHandle h, size_t newType) {
95         return makeHandle(getHandleIndex(h), getHandleGeneration(h), newType);
96     }
97 
EntityManager()98     EntityManager() : EntityManager(0) { }
99 
EntityManager(size_t initialItems)100     EntityManager(size_t initialItems) :
101         mEntries(initialItems),
102         mFirstFreeIndex(0),
103         mLiveEntries(0) {
104         reserve(initialItems);
105     }
106 
~EntityManager()107     ~EntityManager() { clear(); }
108 
109     struct EntityEntry {
110         EntityHandle handle = 0;
111         size_t nextFreeIndex = 0;
112         // 0 is a special generation for brand new entries
113         // that are not used yet
114         size_t liveGeneration = 1;
115         Item item;
116     };
117 
clear()118 	void clear() {
119 		reserve(mEntries.size());
120         mFirstFreeIndex = 0;
121         mLiveEntries = 0;
122     }
123 
nextFreeIndex()124     size_t nextFreeIndex() const {
125         return mFirstFreeIndex;
126     }
127 
add(const Item & item,size_t type)128     EntityHandle add(const Item& item, size_t type) {
129 
130         if (!type) return INVALID_ENTITY_HANDLE;
131 
132         size_t maxElements = (1ULL << indexBits);
133         if (mLiveEntries == maxElements) return INVALID_ENTITY_HANDLE;
134 
135         size_t newIndex = mFirstFreeIndex;
136 
137         EM_DBG("newIndex/firstFree: %zu type: %zu", newIndex, type);
138 
139         size_t neededCapacity = newIndex + 1;
140         if (maxElements < neededCapacity) return INVALID_ENTITY_HANDLE;
141 
142         size_t currentCapacity = mEntries.size();
143         size_t nextCapacity = neededCapacity << 1;
144         if (nextCapacity > maxElements) nextCapacity = maxElements;
145 
146         EM_DBG("needed/current/next capacity: %zu %zu %zu",
147                neededCapacity,
148                currentCapacity,
149                nextCapacity);
150 
151         if (neededCapacity > mEntries.size()) {
152             mEntries.resize(nextCapacity);
153             for (size_t i = currentCapacity; i < nextCapacity; ++i) {
154                 mEntries[i].handle = makeHandle(i, 0, type);
155                 mEntries[i].nextFreeIndex = i + 1;
156                 EM_DBG("new un-init entry: index %zu nextFree %zu",
157                        i, i + 1);
158             }
159         }
160 
161         mEntries[newIndex].handle =
162             makeHandle(newIndex, mEntries[newIndex].liveGeneration, type);
163         mEntries[newIndex].item = item;
164 
165         mFirstFreeIndex = mEntries[newIndex].nextFreeIndex;
166         EM_DBG("created. new first free: %zu", mFirstFreeIndex);
167 
168         ++mLiveEntries;
169 
170         EM_DBG("result handle: 0x%llx", (unsigned long long)mEntries[newIndex].handle);
171 
172         return mEntries[newIndex].handle;
173     }
174 
addFixed(EntityHandle fixedHandle,const Item & item,size_t type)175     EntityHandle addFixed(EntityHandle fixedHandle, const Item& item, size_t type) {
176         // 3 cases:
177         // 1. handle is not allocated and doesn't correspond to mFirstFreeIndex
178         bool isFreeListNonHead = false;
179         // 2. handle already exists (replace)
180         bool isAlloced = false;
181         // 3. index(handle) == mFirstFreeIndex
182         bool isFreeListHead = false;
183 
184         if (!type) return INVALID_ENTITY_HANDLE;
185 
186         size_t maxElements = (1ULL << indexBits);
187         if (mLiveEntries == maxElements) return INVALID_ENTITY_HANDLE;
188 
189         size_t newIndex = getHandleIndex(fixedHandle);
190 
191         EM_DBG("newIndex/firstFree: %zu type: %zu", newIndex, type);
192 
193         size_t neededCapacity = newIndex + 1;
194 
195         if (maxElements < neededCapacity) return INVALID_ENTITY_HANDLE;
196 
197         size_t currentCapacity = mEntries.size();
198         size_t nextCapacity = neededCapacity << 1;
199         if (nextCapacity > maxElements) nextCapacity = maxElements;
200 
201         EM_DBG("needed/current/next capacity: %zu %zu %zu",
202                neededCapacity,
203                currentCapacity,
204                nextCapacity);
205 
206         if (neededCapacity > mEntries.size()) {
207             mEntries.resize(nextCapacity);
208             for (size_t i = currentCapacity; i < nextCapacity; ++i) {
209                 mEntries[i].handle = makeHandle(i, 0, type);
210                 mEntries[i].nextFreeIndex = i + 1;
211                 EM_DBG("new un-init entry: index %zu nextFree %zu",
212                        i, i + 1);
213             }
214         }
215 
216         // Now we ensured that there is enough space to talk about the entry of
217         // this |fixedHandle|.
218         if (mFirstFreeIndex == newIndex) {
219             isFreeListHead = true;
220         } else {
221             auto& entry = mEntries[newIndex];
222             if (entry.liveGeneration == getHandleGeneration(entry.handle)) {
223                 isAlloced = true;
224             } else {
225                 isFreeListNonHead = true;
226             }
227         }
228 
229         mEntries[newIndex].handle = fixedHandle;
230         mEntries[newIndex].liveGeneration = getHandleGeneration(fixedHandle);
231         mEntries[newIndex].item = item;
232 
233         EM_DBG("new index: %zu", newIndex);
234 
235         if (isFreeListHead) {
236 
237             EM_DBG("first free index reset from %zu to %zu",
238                     mFirstFreeIndex, mEntries[newIndex].nextFreeIndex);
239 
240             mFirstFreeIndex = mEntries[newIndex].nextFreeIndex;
241 
242             ++mLiveEntries;
243 
244         } else if (isAlloced) {
245             // Already replaced whatever is there, and since it's already allocated,
246             // no need to update freelist.
247             EM_DBG("entry at %zu already alloced. replacing.", newIndex);
248         } else if (isFreeListNonHead) {
249             // Go through the freelist and skip over the entry we just added.
250             size_t prevEntryIndex = mFirstFreeIndex;
251 
252             EM_DBG("in free list but not head. reorganizing freelist. "
253                    "start at %zu -> %zu",
254                    mFirstFreeIndex, mEntries[prevEntryIndex].nextFreeIndex);
255 
256             while (mEntries[prevEntryIndex].nextFreeIndex != newIndex) {
257                 EM_DBG("next: %zu -> %zu",
258                        prevEntryIndex,
259                        mEntries[prevEntryIndex].nextFreeIndex);
260                 prevEntryIndex =
261                     mEntries[prevEntryIndex].nextFreeIndex;
262             }
263 
264             EM_DBG("finished. set prev entry %zu to new entry's next, %zu",
265                     prevEntryIndex, mEntries[newIndex].nextFreeIndex);
266 
267             mEntries[prevEntryIndex].nextFreeIndex =
268                 mEntries[newIndex].nextFreeIndex;
269 
270             ++mLiveEntries;
271         }
272 
273         return fixedHandle;
274     }
remove(EntityHandle h)275     void remove(EntityHandle h) {
276 
277         if (get(h) == nullptr) return;
278 
279         size_t index = getHandleIndex(h);
280 
281         EM_DBG("remove handle: 0x%llx -> index %zu", (unsigned long long)h, index);
282 
283         auto& entry = mEntries[index];
284 
285         EM_DBG("handle gen: %zu entry gen: %zu", getHandleGeneration(h), entry.liveGeneration);
286 
287         ++entry.liveGeneration;
288         if ((entry.liveGeneration == 0) ||
289             (entry.liveGeneration == (1ULL << generationBits))) {
290             entry.liveGeneration = 1;
291         }
292 
293         entry.nextFreeIndex = mFirstFreeIndex;
294 
295         mFirstFreeIndex = index;
296 
297         EM_DBG("new first free: %zu next free: %zu", mFirstFreeIndex, entry.nextFreeIndex);
298 
299         --mLiveEntries;
300     }
301 
get(EntityHandle h)302     Item* get(EntityHandle h) {
303         EM_DBG("get 0x%llx", (unsigned long long)h);
304         size_t index = getHandleIndex(h);
305         if (index >= mEntries.size()) {
306             return nullptr;
307         }
308 
309         auto& entry = mEntries[index];
310         if (entry.liveGeneration != getHandleGeneration(h)) {
311             return nullptr;
312         }
313 
314         return &entry.item;
315     }
316 
get_const(EntityHandle h)317     const Item* get_const(EntityHandle h) const {
318         size_t index = getHandleIndex(h);
319         if (index >= mEntries.size()) return nullptr;
320 
321         const auto& entry = mEntries.data() + index;
322         if (entry->liveGeneration != getHandleGeneration(h)) return nullptr;
323 
324         return &entry->item;
325     }
326 
isLive(EntityHandle h)327     bool isLive(EntityHandle h) const {
328         size_t index = getHandleIndex(h);
329         if (index >= mEntries.size()) return false;
330 
331         const auto& entry = mEntries[index];
332 
333         return (entry.liveGeneration == getHandleGeneration(h));
334     }
335 
forEachEntry(IteratorFunc func)336     void forEachEntry(IteratorFunc func) {
337         for (auto& entry: mEntries) {
338             auto handle = entry.handle;
339             bool live = isLive(handle);
340             auto& item = entry.item;
341             func(live, handle, item);
342         }
343     }
344 
forEachLiveEntry(IteratorFunc func)345     void forEachLiveEntry(IteratorFunc func) {
346         for (auto& entry: mEntries) {
347             auto handle = entry.handle;
348             bool live = isLive(handle);
349 
350             if (!live) continue;
351 
352             auto& item = entry.item;
353             func(live, handle, item);
354         }
355     }
356 
forEachLiveEntry_const(ConstIteratorFunc func)357     void forEachLiveEntry_const(ConstIteratorFunc func) const {
358         for (auto& entry: mEntries) {
359             auto handle = entry.handle;
360             bool live = isLive(handle);
361 
362             if (!live) continue;
363 
364             const auto& item = entry.item;
365             func(live, handle, item);
366         }
367     }
368 
369 private:
reserve(size_t count)370     void reserve(size_t count) {
371         if (mEntries.size() < count) {
372             mEntries.resize(count);
373         }
374         for (size_t i = 0; i < count; ++i) {
375             mEntries[i].handle = makeHandle(i, 0, 1);
376             mEntries[i].nextFreeIndex = i + 1;
377             ++mEntries[i].liveGeneration;
378             if ((mEntries[i].liveGeneration == 0) ||
379                     (mEntries[i].liveGeneration == (1ULL << generationBits))) {
380                 mEntries[i].liveGeneration = 1;
381             }
382             EM_DBG("new un-init entry: index %zu nextFree %zu",
383                     i, i + 1);
384         }
385     }
386 
387     std::vector<EntityEntry> mEntries;
388     size_t mFirstFreeIndex;
389     size_t mLiveEntries;
390 };
391 
392 // Tracks components over a given space of entities.
393 // Looking up by entity index is slower, but takes less space overall versus
394 // a flat array that parallels the entities.
395 template<size_t indexBits,
396          size_t generationBits,
397          size_t typeBits,
398          class Data>
399 class ComponentManager {
400 public:
401 
402     static_assert(64 == (indexBits + generationBits + typeBits),
403                   "bits of index, generation, and type must add to 64");
404 
405     using ComponentHandle = uint64_t;
406     using EntityHandle = uint64_t;
407     using ComponentIteratorFunc = std::function<void(bool, ComponentHandle componentHandle, EntityHandle entityHandle, Data& data)>;
408     using ConstComponentIteratorFunc = std::function<void(bool, ComponentHandle componentHandle, EntityHandle entityHandle, const Data& data)>;
409 
410     // Adds the given |data| and associates it with EntityHandle.
411     // We can also opt-in to immediately tracking the handle in the reverse mapping,
412     // which has an upfront cost in runtime.
413     // Many uses of ComponentManager don't really need to track the associated entity handle,
414     // so it is opt-in.
415 
416     ComponentHandle add(
417         EntityHandle h,
418         const Data& data,
419         size_t type,
420         bool tracked = false) {
421 
422         InternalItem item = { h, data, tracked };
423         auto res = static_cast<ComponentHandle>(mData.add(item, type));
424 
425         if (tracked) {
426             mEntityToComponentMap[h] = res;
427         }
428 
429         return res;
430     }
431 
clear()432     void clear() {
433         mData.clear();
434         mEntityToComponentMap.clear();
435     }
436 
437     // If we didn't explicitly track, just fail.
getComponentHandle(EntityHandle h)438     ComponentHandle getComponentHandle(EntityHandle h) const {
439         auto componentHandlePtr = android::base::find(mEntityToComponentMap, h);
440         if (!componentHandlePtr) return INVALID_COMPONENT_HANDLE;
441         return *componentHandlePtr;
442     }
443 
getEntityHandle(ComponentHandle h)444     EntityHandle getEntityHandle(ComponentHandle h) const {
445         return mData.get(h)->entityHandle;
446     }
447 
removeByEntity(EntityHandle h)448     void removeByEntity(EntityHandle h) {
449         auto componentHandle = getComponentHandle(h);
450         removeByComponent(componentHandle);
451     }
452 
removeByComponent(ComponentHandle h)453     void removeByComponent(ComponentHandle h) {
454         auto item = mData.get(h);
455 
456         if (!item) return;
457         if (item->tracked) {
458             mEntityToComponentMap.erase(item->entityHandle);
459         }
460 
461         mData.remove(h);
462     }
463 
getByEntity(EntityHandle h)464     Data* getByEntity(EntityHandle h) {
465         return getByComponent(getComponentHandle(h));
466     }
467 
getByComponent(ComponentHandle h)468     Data* getByComponent(ComponentHandle h) {
469         auto item = mData.get(h);
470         if (!item) return nullptr;
471         return &(item->data);
472     }
473 
forEachComponent(ComponentIteratorFunc func)474     void forEachComponent(ComponentIteratorFunc func) {
475         mData.forEachEntry(
476             [func](bool live, typename InternalEntityManager::EntityHandle componentHandle, InternalItem& item) {
477                 func(live, componentHandle, item.entityHandle, item.data);
478         });
479     }
480 
forEachLiveComponent(ComponentIteratorFunc func)481     void forEachLiveComponent(ComponentIteratorFunc func) {
482         mData.forEachLiveEntry(
483             [func](bool live, typename InternalEntityManager::EntityHandle componentHandle, InternalItem& item) {
484                 func(live, componentHandle, item.entityHandle, item.data);
485         });
486     }
487 
forEachLiveComponent_const(ConstComponentIteratorFunc func)488     void forEachLiveComponent_const(ConstComponentIteratorFunc func) const {
489         mData.forEachLiveEntry_const(
490             [func](bool live, typename InternalEntityManager::EntityHandle componentHandle, const InternalItem& item) {
491                 func(live, componentHandle, item.entityHandle, item.data);
492         });
493     }
494 
495 private:
496     struct InternalItem {
497         EntityHandle entityHandle;
498         Data data;
499         bool tracked;
500     };
501 
502     using InternalEntityManager = EntityManager<indexBits, generationBits, typeBits, InternalItem>;
503     using EntityToComponentMap = std::unordered_map<EntityHandle, ComponentHandle>;
504 
505     mutable InternalEntityManager mData;
506     EntityToComponentMap mEntityToComponentMap;
507 };
508 
509 // ComponentManager, but unpacked; uses the same index space as the associated
510 // entities. Takes more space by default, but not more if all entities have this component.
511 template<size_t indexBits,
512          size_t generationBits,
513          size_t typeBits,
514          class Data>
515 class UnpackedComponentManager {
516 public:
517     using ComponentHandle = uint64_t;
518     using EntityHandle = uint64_t;
519     using ComponentIteratorFunc =
520         std::function<void(bool, ComponentHandle componentHandle, EntityHandle entityHandle, Data& data)>;
521     using ConstComponentIteratorFunc =
522         std::function<void(bool, ComponentHandle componentHandle, EntityHandle entityHandle, const Data& data)>;
523 
add(EntityHandle h,const Data & data)524     EntityHandle add(EntityHandle h, const Data& data) {
525 
526         size_t index = indexOfEntity(h);
527 
528         if (index + 1 > mItems.size()) {
529             mItems.resize((index + 1) * 2);
530         }
531 
532         mItems[index].live = true;
533         mItems[index].handle = h;
534         mItems[index].data = data;
535 
536         return h;
537     }
538 
clear()539     void clear() {
540         mItems.clear();
541     }
542 
remove(EntityHandle h)543     void remove(EntityHandle h) {
544         size_t index = indexOfEntity(h);
545         if (index >= mItems.size()) return;
546         mItems[index].live = false;
547     }
548 
get(EntityHandle h)549     Data* get(EntityHandle h) {
550         size_t index = indexOfEntity(h);
551 
552         if (index + 1 > mItems.size()) {
553             mItems.resize((index + 1) * 2);
554         }
555 
556         auto item = mItems.data() + index;
557         if (!item->live) return nullptr;
558         return &item->data;
559     }
560 
get_const(EntityHandle h)561     const Data* get_const(EntityHandle h) const {
562         size_t index = indexOfEntity(h);
563 
564         if (index + 1 > mItems.size()) {
565             return nullptr;
566         }
567 
568         auto item = mItems.data() + index;
569         if (!item->live) return nullptr;
570         return &item->data;
571     }
572 
forEachComponent(ComponentIteratorFunc func)573     void forEachComponent(ComponentIteratorFunc func) {
574         for (auto& item : mItems) {
575             func(item.live, item.handle, item.handle, item.data);
576         }
577     }
578 
forEachLiveComponent(ComponentIteratorFunc func)579     void forEachLiveComponent(ComponentIteratorFunc func) {
580         for (auto& item : mItems) {
581             if (item.live) func(item.live, item.handle, item.handle, item.data);
582         }
583     }
584 
forEachLiveComponent_const(ConstComponentIteratorFunc func)585     void forEachLiveComponent_const(ConstComponentIteratorFunc func) const {
586         for (auto& item : mItems) {
587             if (item.live) func(item.live, item.handle, item.handle, item.data);
588         }
589     }
590 
591 private:
indexOfEntity(EntityHandle h)592     static size_t indexOfEntity(EntityHandle h) {
593         return EntityManager<indexBits, generationBits, typeBits, int>::getHandleIndex(h);
594     }
595 
596     struct InternalItem {
597         bool live = false;
598         EntityHandle handle = 0;
599         Data data;
600     };
601 
602     std::vector<InternalItem> mItems;
603 };
604 
605 } // namespace android
606 } // namespace base
607