• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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