1 // Copyright (C) 2020 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/containers/EntityManager.h"
18 
19 #include <unordered_map>
20 
21 namespace gfxstream {
22 namespace guest {
23 
24 template <size_t maxIndex,
25           class IndexType, // must be castable to uint64_t
26           class Data>
27 class HybridComponentManager {
28 public:
29     using UCM = UnpackedComponentManager<32, 16, 16, Data>;
30     using EM = EntityManager<32, 16, 16, Data>;
31     using IterFunc = typename UCM::ComponentIteratorFunc;
32     using ConstIterFunc = typename UCM::ConstComponentIteratorFunc;
33     using Handle = typename EM::EntityHandle;
34 
add(IndexType index,const Data & data)35     void add(IndexType index, const Data& data) {
36         uint64_t index_u64 = (uint64_t)index;
37         if (index_u64 < maxIndex) {
38             auto internal_handle = index2Handle(index_u64);
39             mComponentManager.add(internal_handle, data);
40         } else {
41             mMap[index] = data;
42         }
43 
44     }
45 
clear()46     void clear() {
47         mComponentManager.clear();
48         mMap.clear();
49     }
50 
remove(IndexType index)51     void remove(IndexType index) {
52         uint64_t index_u64 = (uint64_t)index;
53         if (index_u64 < maxIndex) {
54             auto internal_handle = index2Handle(index_u64);
55             mComponentManager.remove(internal_handle);
56         } else {
57             mMap.erase(index);
58         }
59     }
60 
get(IndexType index)61     Data* get(IndexType index) {
62         uint64_t index_u64 = (uint64_t)index;
63         if (index_u64 < maxIndex) {
64             auto internal_handle = index2Handle(index_u64);
65             return mComponentManager.get(internal_handle);
66         } else {
67             return gfxstream::guest::find(mMap, index);
68         }
69     }
70 
get_const(IndexType index)71     const Data* get_const(IndexType index) const {
72         uint64_t index_u64 = (uint64_t)index;
73         if (index_u64 < maxIndex) {
74             auto internal_handle = index2Handle(index_u64);
75             return mComponentManager.get_const(internal_handle);
76         } else {
77             return gfxstream::guest::find(mMap, index);
78         }
79     }
80 
getExceptZero(IndexType index)81     Data* getExceptZero(IndexType index) {
82         Data* res = get(index);
83         if (!res) return nullptr;
84         if (!(*res)) return nullptr;
85         return res;
86     }
87 
getExceptZero_const(IndexType index)88     const Data* getExceptZero_const(IndexType index) const {
89         const Data* res = get_const(index);
90         if (!res) return nullptr;
91         if (!(*res)) return nullptr;
92         return res;
93     }
94 
forEach(IterFunc func)95     void forEach(IterFunc func) {
96         mComponentManager.forEach(func);
97 
98         for (auto it : mMap) {
99             auto handle = index2Handle(it.first);
100             func(true /* live */, handle, handle, it.second);
101         }
102     }
103 
forEachLive(IterFunc func)104     void forEachLive(IterFunc func) {
105         mComponentManager.forEachLiveComponent(func);
106 
107         for (auto it : mMap) {
108             auto handle = index2Handle(it.first);
109             func(true /* live */, handle, handle, it.second);
110         }
111     }
112 
forEachLive_const(ConstIterFunc func)113     void forEachLive_const(ConstIterFunc func) const {
114         mComponentManager.forEachLiveComponent_const(func);
115 
116         for (const auto it : mMap) {
117             auto handle = index2Handle(it.first);
118             func(true /* live */, handle, handle, it.second);
119         }
120     }
121 
122 private:
index2Handle(uint64_t index)123     static Handle index2Handle(uint64_t index) {
124         return EM::makeHandle((uint32_t)index, 1, 1);
125     }
126 
127     UCM mComponentManager;
128     std::unordered_map<IndexType, Data> mMap;
129 };
130 
131 } // namespace android
132 } // namespace base
133