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