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 "render_data_store_manager.h"
17
18 #include <cstddef>
19
20 #include <base/util/uid_util.h>
21 #include <render/datastore/intf_render_data_store.h>
22 #include <render/device/intf_device.h>
23 #include <render/namespace.h>
24
25 #include "util/log.h"
26
27 using namespace BASE_NS;
28
RENDER_BEGIN_NAMESPACE()29 RENDER_BEGIN_NAMESPACE()
30 RenderDataStoreManager::RenderDataStoreManager(IRenderContext& renderContext) : renderContext_(renderContext) {}
31
PreRender()32 void RenderDataStoreManager::PreRender()
33 {
34 decltype(pendingRenderAccess_) pendingRenderAccess;
35 {
36 std::lock_guard<std::mutex> lock(mutex_);
37 pendingRenderAccess = std::move(pendingRenderAccess_);
38 }
39
40 // prepare access for render time access
41 for (auto& pendingRef : pendingRenderAccess) {
42 if (pendingRef.destroy) { // remove deferred destruction stores
43 renderAccessStores_.erase(pendingRef.hash);
44 } else {
45 PLUGIN_ASSERT(pendingRef.renderDataStore);
46 renderAccessStores_.insert_or_assign(pendingRef.hash, pendingRef.renderDataStore);
47 }
48 }
49
50 // all valid stores can be accessed from render access stores without locks
51 for (const auto& ref : renderAccessStores_) {
52 ref.second->PreRender();
53 }
54 }
55
PreRenderBackend()56 void RenderDataStoreManager::PreRenderBackend()
57 {
58 // all valid stores can be accessed from render access stores without locks
59 for (const auto& ref : renderAccessStores_) {
60 ref.second->PreRenderBackend();
61 }
62 }
63
PostRender()64 void RenderDataStoreManager::PostRender()
65 {
66 // all valid stores can be accessed from render access stores without locks
67 for (const auto& ref : renderAccessStores_) {
68 ref.second->PostRender();
69 }
70
71 DeferredDestruction();
72 }
73
GetRenderDataStore(const string_view name) const74 IRenderDataStore* RenderDataStoreManager::GetRenderDataStore(const string_view name) const
75 {
76 auto const nameHash = hash(name);
77
78 std::lock_guard<std::mutex> lock(mutex_);
79
80 if (const auto iter = stores_.find(nameHash); iter != stores_.cend()) {
81 return iter->second.get();
82 } else {
83 PLUGIN_LOG_E("render data store: (%s), not found", name.data());
84 return nullptr;
85 }
86 }
87
GetRenderTimeRenderDataStore(const string_view name) const88 IRenderDataStore* RenderDataStoreManager::GetRenderTimeRenderDataStore(const string_view name) const
89 {
90 // not locked
91
92 auto const nameHash = hash(name);
93 if (const auto iter = renderAccessStores_.find(nameHash); iter != renderAccessStores_.cend()) {
94 return iter->second;
95 } else {
96 PLUGIN_LOG_E("render data store: (%s), not found", name.data());
97 return nullptr;
98 }
99 }
100
Create(const Uid & dataStoreTypeUid,char const * dataStoreName)101 IRenderDataStore* RenderDataStoreManager::Create(const Uid& dataStoreTypeUid, char const* dataStoreName)
102 {
103 auto const dataStoreTypeHash = hash(dataStoreTypeUid);
104 if (auto const factoryIt = factories_.find(dataStoreTypeHash); factoryIt != factories_.end()) {
105 auto const dataStoreNameHash = hash(string_view(dataStoreName));
106 IRenderDataStore* dataStore = nullptr;
107
108 std::lock_guard<std::mutex> lock(mutex_);
109
110 if (auto const namedStoreIt = stores_.find(dataStoreNameHash); namedStoreIt != stores_.cend()) {
111 PLUGIN_LOG_D("Named data store already exists (type: %s) (name: %s)", to_string(dataStoreTypeUid).data(),
112 dataStoreName);
113 dataStore = namedStoreIt->second.get();
114 if (dataStore->GetUid() != dataStoreTypeUid) {
115 PLUGIN_LOG_E("Named data store (type: %s, name: %s) exists with different type (%s)",
116 to_string(dataStoreTypeUid).data(), dataStoreName, dataStore->GetTypeName().data());
117 dataStore = nullptr;
118 }
119 } else {
120 auto const dataStoreIt = stores_.insert_or_assign(dataStoreNameHash,
121 RenderDataStorePtr { factoryIt->second.createDataStore(renderContext_, dataStoreName),
122 factoryIt->second.destroyDataStore });
123 pointerToStoreHash_.insert_or_assign(dataStoreIt.first->second.get(), uint64_t { dataStoreNameHash });
124 dataStore = dataStoreIt.first->second.get();
125 }
126
127 pendingRenderAccess_.push_back({ dataStoreNameHash, dataStore, false });
128 return dataStore;
129 } else {
130 PLUGIN_LOG_E("render data store type not found (type: %s) (named: %s)", to_string(dataStoreTypeUid).data(),
131 dataStoreName);
132 PLUGIN_ASSERT(false);
133 }
134 return nullptr;
135 }
136
Destroy(const Uid & dataStoreTypeUid,IRenderDataStore * instance)137 void RenderDataStoreManager::Destroy(const Uid& dataStoreTypeUid, IRenderDataStore* instance)
138 {
139 if (instance) {
140 const size_t typeHash = hash(dataStoreTypeUid);
141
142 std::lock_guard<std::mutex> lock(mutex_);
143
144 deferredDestructionDataStores_.push_back({ typeHash, instance });
145
146 PLUGIN_ASSERT(pointerToStoreHash_.contains(instance));
147 if (auto const storeIt = pointerToStoreHash_.find(instance); storeIt != pointerToStoreHash_.cend()) {
148 pendingRenderAccess_.push_back({ storeIt->second, instance, true });
149 }
150 }
151 }
152
DeferredDestruction()153 void RenderDataStoreManager::DeferredDestruction()
154 {
155 std::lock_guard<std::mutex> lock(mutex_);
156
157 for (const auto& destroyRef : deferredDestructionDataStores_) {
158 if (auto const pos = factories_.find(destroyRef.dataStoreHash); pos != factories_.end()) {
159 if (auto const storeIt = pointerToStoreHash_.find(destroyRef.instance);
160 storeIt != pointerToStoreHash_.cend()) {
161 stores_.erase(storeIt->second);
162 pointerToStoreHash_.erase(storeIt);
163 }
164 }
165 }
166 deferredDestructionDataStores_.clear();
167 }
168
AddRenderDataStoreFactory(const RenderDataStoreTypeInfo & typeInfo)169 void RenderDataStoreManager::AddRenderDataStoreFactory(const RenderDataStoreTypeInfo& typeInfo)
170 {
171 // plugin load and factory addition is sequential
172 // not locked access
173
174 if (typeInfo.createDataStore && typeInfo.destroyDataStore) {
175 auto const dataStoreTypeHash = hash(typeInfo.uid);
176 factories_.insert({ dataStoreTypeHash, typeInfo });
177 } else {
178 PLUGIN_LOG_E("RenderDataStoreTypeInfo must provide non-null function pointers");
179 PLUGIN_ASSERT(typeInfo.createDataStore && "createDataStore cannot be null");
180 PLUGIN_ASSERT(typeInfo.destroyDataStore && "destroyDataStore cannot be null");
181 }
182 }
183
RemoveRenderDataStoreFactory(const RenderDataStoreTypeInfo & typeInfo)184 void RenderDataStoreManager::RemoveRenderDataStoreFactory(const RenderDataStoreTypeInfo& typeInfo)
185 {
186 for (auto b = pointerToStoreHash_.begin(), e = pointerToStoreHash_.end(); b != e;) {
187 if (b->first->GetUid() == typeInfo.uid) {
188 stores_.erase(b->second);
189 b = pointerToStoreHash_.erase(b);
190 } else {
191 ++b;
192 }
193 }
194 auto const dataStoreTypeHash = hash(typeInfo.uid);
195 factories_.erase(dataStoreTypeHash);
196 }
197
RenderNodeRenderDataStoreManager(const RenderDataStoreManager & renderDataStoreMgr)198 RenderNodeRenderDataStoreManager::RenderNodeRenderDataStoreManager(const RenderDataStoreManager& renderDataStoreMgr)
199 : renderDataStoreMgr_(renderDataStoreMgr)
200 {}
201
GetRenderDataStore(const string_view name) const202 IRenderDataStore* RenderNodeRenderDataStoreManager::GetRenderDataStore(const string_view name) const
203 {
204 return renderDataStoreMgr_.GetRenderTimeRenderDataStore(name);
205 }
206 RENDER_END_NAMESPACE()
207