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