1 /*
2 * Copyright (c) 2022 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_pod.h"
17
18 #include <algorithm>
19 #include <cstdint>
20
21 #include <base/containers/array_view.h>
22 #include <render/namespace.h>
23
24 #include "util/log.h"
25
26 using namespace BASE_NS;
27
RENDER_BEGIN_NAMESPACE()28 RENDER_BEGIN_NAMESPACE()
29 RenderDataStorePod::RenderDataStorePod(const string_view name) : name_(name) {}
30
Ref()31 void RenderDataStorePod::Ref()
32 {
33 refcnt_.fetch_add(1, std::memory_order_relaxed);
34 }
35
Unref()36 void RenderDataStorePod::Unref()
37 {
38 if (std::atomic_fetch_sub_explicit(&refcnt_, 1, std::memory_order_release) == 1) {
39 std::atomic_thread_fence(std::memory_order_acquire);
40 delete this;
41 }
42 }
43
GetRefCount()44 int32_t RenderDataStorePod::GetRefCount()
45 {
46 return refcnt_;
47 }
48
CreatePod(const string_view tpName,const string_view name,const array_view<const uint8_t> srcData)49 void RenderDataStorePod::CreatePod(
50 const string_view tpName, const string_view name, const array_view<const uint8_t> srcData)
51 {
52 if (srcData.empty()) {
53 PLUGIN_LOG_W("Zero size pod is not created (name: %s)", tpName.data());
54 return;
55 }
56 bool contains = false;
57 {
58 const auto lock = std::lock_guard(mutex_);
59
60 contains = nameToDataOffset_.contains(name);
61 if (!contains) {
62 const size_t prevByteSize = dataStore_.size();
63 const size_t newByteSize = prevByteSize + srcData.size();
64 dataStore_.resize(newByteSize);
65 uint8_t* dst = &dataStore_[prevByteSize];
66 if (!CloneData(dst, dataStore_.size() - prevByteSize, srcData.data(), srcData.size())) {
67 PLUGIN_LOG_E("Copying of RenderDataStorePod Data failed.");
68 }
69
70 auto& typeNameRef = typeNameToPodNames_[tpName];
71 nameToDataOffset_[name] = { static_cast<uint32_t>(prevByteSize), static_cast<uint32_t>(srcData.size()) };
72 typeNameRef.emplace_back(name);
73 }
74 } // end of lock
75
76 // already created, set data
77 if (contains) {
78 PLUGIN_LOG_I("updating already created pod: %s", name.data());
79 Set(name, srcData);
80 }
81 }
82
DestroyPod(const string_view typeName,const string_view name)83 void RenderDataStorePod::DestroyPod(const string_view typeName, const string_view name)
84 {
85 const auto lock = std::lock_guard(mutex_);
86
87 if (const auto iter = nameToDataOffset_.find(name); iter != nameToDataOffset_.end()) {
88 const auto offsetToData = iter->second;
89 PLUGIN_ASSERT(offsetToData.index + offsetToData.byteSize <= (uint32_t)dataStore_.size());
90 const auto first = dataStore_.cbegin() + static_cast<int32_t>(offsetToData.index);
91 const auto last = first + static_cast<int32_t>(offsetToData.byteSize);
92 dataStore_.erase(first, last);
93 nameToDataOffset_.erase(iter);
94 // move the index of pods after the destroyed pod by the size of the pod
95 for (auto& nameToOffset : nameToDataOffset_) {
96 if (nameToOffset.second.index > offsetToData.index) {
97 nameToOffset.second.index -= offsetToData.byteSize;
98 }
99 }
100 if (auto tpIter = typeNameToPodNames_.find(typeName); tpIter != typeNameToPodNames_.end()) {
101 for (auto nameIter = tpIter->second.cbegin(); nameIter != tpIter->second.cend(); ++nameIter) {
102 if (*nameIter == name) {
103 tpIter->second.erase(nameIter);
104 break;
105 }
106 }
107 }
108 } else {
109 PLUGIN_LOG_I("pod not found: %s", name.data());
110 }
111 }
112
Set(const string_view name,const array_view<const uint8_t> srcData)113 void RenderDataStorePod::Set(const string_view name, const array_view<const uint8_t> srcData)
114 {
115 const auto lock = std::lock_guard(mutex_);
116
117 const auto iter = nameToDataOffset_.find(name);
118 if (iter != nameToDataOffset_.cend()) {
119 const uint32_t index = iter->second.index;
120 const uint32_t byteSize = iter->second.byteSize;
121 PLUGIN_ASSERT(index + byteSize <= (uint32_t)dataStore_.size());
122 PLUGIN_ASSERT(srcData.size() <= byteSize);
123
124 const uint32_t maxByteSize = std::min(byteSize, static_cast<uint32_t>(srcData.size()));
125
126 uint8_t* dst = &dataStore_[index];
127 if (!CloneData(dst, dataStore_.size() - index, srcData.data(), maxByteSize)) {
128 PLUGIN_LOG_E("Copying of RenderDataStorePod Data failed.");
129 }
130 } else {
131 PLUGIN_LOG_E("render data store pod: %s not created", name.data());
132 }
133 }
134
Get(const string_view name) const135 array_view<const uint8_t> RenderDataStorePod::Get(const string_view name) const
136 {
137 const auto lock = std::lock_guard(mutex_);
138
139 array_view<const uint8_t> view;
140 const auto iter = nameToDataOffset_.find(name);
141 if (iter != nameToDataOffset_.cend()) {
142 const uint32_t index = iter->second.index;
143 const uint32_t byteSize = iter->second.byteSize;
144 PLUGIN_ASSERT(index + byteSize <= (uint32_t)dataStore_.size());
145
146 const uint8_t* data = &dataStore_[index];
147 view = array_view<const uint8_t>(data, byteSize);
148 }
149 return view;
150 }
151
GetPodNames(const string_view tpName) const152 array_view<const string> RenderDataStorePod::GetPodNames(const string_view tpName) const
153 {
154 const auto lock = std::lock_guard(mutex_);
155
156 const auto iter = typeNameToPodNames_.find(tpName);
157 if (iter != typeNameToPodNames_.cend()) {
158 return { iter->second.data(), iter->second.size() };
159 } else {
160 PLUGIN_LOG_I("render data store pod type (%s), not found", tpName.data());
161 return {};
162 }
163 }
164
165 // for plugin / factory interface
Create(IRenderContext &,const char * name)166 refcnt_ptr<IRenderDataStore> RenderDataStorePod::Create(IRenderContext&, const char* name)
167 {
168 return refcnt_ptr<IRenderDataStore>(new RenderDataStorePod(name));
169 }
170 RENDER_END_NAMESPACE()
171