1 /*
2 * Copyright (c) 2024 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 #include "stack_property.h"
16
17 #include <meta/api/util.h>
18 #include <meta/base/interface_utils.h>
19 #include <meta/ext/serialization/serializer.h>
20 #include <meta/interface/property/intf_stack_resetable.h>
21
22 #include "any.h"
23 #include "dependencies.h"
24
25 META_BEGIN_NAMESPACE()
26 namespace Internal {
27
StackProperty(BASE_NS::string name)28 StackProperty::StackProperty(BASE_NS::string name)
29 : Super(BASE_NS::move(name)), onChangedCallback_(MakeCallback<IOnChanged>([this] { InternalOnChanged(); }))
30 {}
31
~StackProperty()32 StackProperty::~StackProperty()
33 {
34 CleanUp();
35 }
36
CleanUp()37 void StackProperty::CleanUp()
38 {
39 if (auto i = interface_cast<INotifyOnChange>(defaultValue_)) {
40 i->OnChanged()->RemoveHandler(uintptr_t(this));
41 }
42 for (auto&& m : modifiers_) {
43 if (auto i = interface_cast<INotifyOnChange>(m)) {
44 i->OnChanged()->RemoveHandler(uintptr_t(this));
45 }
46 }
47 modifiers_.clear();
48 for (auto&& v : values_) {
49 if (auto i = interface_cast<INotifyOnChange>(v)) {
50 i->OnChanged()->RemoveHandler(uintptr_t(this));
51 }
52 }
53 values_.clear();
54 }
55
TryToSetToValue(const IAny & v,IValue::Ptr & value)56 AnyReturnValue StackProperty::TryToSetToValue(const IAny& v, IValue::Ptr& value)
57 {
58 AnyReturnValue res = AnyReturn::FAIL;
59
60 auto noti = interface_cast<INotifyOnChange>(value);
61 InterfaceUniqueLock lock { value };
62 if (noti) {
63 noti->OnChanged()->EnableHandler(uintptr_t(this), false);
64 }
65 res = value->SetValue(v);
66 if (res) {
67 if (noti) {
68 noti->OnChanged()->EnableHandler(uintptr_t(this), true);
69 }
70 }
71 return res;
72 }
73
SetValueInValueStack(const IAny & value)74 AnyReturnValue StackProperty::SetValueInValueStack(const IAny& value)
75 {
76 AnyReturnValue res = AnyReturn::FAIL;
77 // find first value that accepts the new value, all non-accepting values are removed
78 for (int i = int(values_.size()) - 1; i >= 0; --i) {
79 res = TryToSetToValue(value, values_[i]);
80 if (res) {
81 break;
82 }
83 if (auto noti = interface_cast<INotifyOnChange>(values_[i])) {
84 noti->OnChanged()->RemoveHandler(uintptr_t(this), true);
85 }
86 values_.pop_back();
87 }
88 // if there was no any to set the new value, create one
89 if (!res) {
90 if (auto c = interface_pointer_cast<IValue>(value.Clone(true))) {
91 if (auto i = interface_cast<INotifyOnChange>(c)) {
92 i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
93 }
94 values_.push_back(c);
95 res = AnyReturn::SUCCESS;
96 } else {
97 res = AnyReturn::INCOMPATIBLE_TYPE;
98 }
99 }
100 return res;
101 }
102
SetValueToStack(const IAny::Ptr & internal)103 AnyReturnValue StackProperty::SetValueToStack(const IAny::Ptr& internal)
104 {
105 // first go through modifiers and let them alter the value
106 for (auto it = modifiers_.rbegin(); it != modifiers_.rend(); ++it) {
107 auto m = (*it)->ProcessOnSet(*internal, GetValueFromStack());
108 if (m & EVAL_ERROR) {
109 return AnyReturn::FAIL;
110 }
111 if (m & EVAL_RETURN) {
112 if (m & EVAL_VALUE_CHANGED) {
113 NotifyChange();
114 }
115 return AnyReturn::SUCCESS;
116 }
117 }
118
119 auto res = SetValueInValueStack(*internal);
120 if (res != AnyReturn::NOTHING_TO_DO) {
121 // reset cached value so that shared_ptrs et al get destroyed
122 currentValue_->ResetValue();
123 NotifyChange();
124 }
125 return res;
126 }
SetValue(const IAny & value)127 AnyReturnValue StackProperty::SetValue(const IAny& value)
128 {
129 if (evaluating_) {
130 CORE_LOG_E("Recursive property evaluation requested [property name=%s]", GetName().c_str());
131 return AnyReturn::RECURSIVE_CALL;
132 }
133 evaluating_ = true;
134
135 AnyReturnValue res = AnyReturn::SUCCESS;
136
137 auto v = GetData();
138 if (!v) {
139 CORE_LOG_D("Initializing internal any with SetValue");
140 res = SetInternalAny(value.Clone(false));
141 if (res) {
142 v = GetData();
143 }
144 }
145 if (res) {
146 CORE_ASSERT_MSG(v, "Internal any not set");
147 res = SetInternalValue(value);
148 if (res) {
149 res = SetValueToStack(v);
150 }
151 if (res) {
152 SetDefaultValueFlag(false);
153 }
154 }
155
156 evaluating_ = false;
157 if (HasPendingInvoke() && !locked_) {
158 SetPendingInvoke(false);
159 InvokeOnChanged(onChanged_, owner_);
160 }
161 return res;
162 }
GetValueFromStack() const163 const IAny& StackProperty::GetValueFromStack() const
164 {
165 if (requiresEvaluation_) {
166 AnyReturnValue res = AnyReturn::FAIL;
167 if (values_.empty()) {
168 res = currentValue_->CopyFrom(*defaultValue_);
169 } else {
170 auto& v = values_.back();
171 InterfaceSharedLock lock { v };
172 res = currentValue_->CopyFrom(v->GetValue());
173 }
174 if (!res) {
175 CORE_LOG_E("Invalid value in stack, could not copy from [property name=%s]", GetName().c_str());
176 return INVALID_ANY;
177 }
178 for (auto&& m : modifiers_) {
179 auto mres = m->ProcessOnGet(*currentValue_);
180 if (mres & EVAL_RETURN) {
181 break;
182 }
183 }
184 requiresEvaluation_ = false;
185 }
186 return *currentValue_;
187 }
RawGetValue() const188 const IAny& StackProperty::RawGetValue() const
189 {
190 if (evaluating_) {
191 CORE_LOG_E("Recursive property evaluation requested [property name=%s]", GetName().c_str());
192 return INVALID_ANY;
193 }
194 if (!currentValue_) {
195 CORE_LOG_E("GetValue called for not initialized property [property name=%s]", GetName().c_str());
196 return INVALID_ANY;
197 }
198 evaluating_ = true;
199 const IAny& res = GetValueFromStack();
200 evaluating_ = false;
201 return res;
202 }
203
EvaluateAndStore()204 void StackProperty::EvaluateAndStore()
205 {
206 // evaluate
207 const IAny& res = RawGetValue();
208 // store
209 if (auto v = TopValue()) {
210 TryToSetToValue(res, v);
211 }
212 }
213
GetValue() const214 const IAny& StackProperty::GetValue() const
215 {
216 bool isActive = false;
217 if constexpr (ENABLE_DEPENDENCY_CHECK) {
218 auto& d = GetDeps();
219 if (d.IsActive()) {
220 if (!d.AddDependency(self_.lock())) {
221 return INVALID_ANY;
222 }
223 // force evaluation since we are checking dependencies
224 requiresEvaluation_ = true;
225 isActive = true;
226 d.Start();
227 }
228 }
229 const IAny& res = RawGetValue();
230 if constexpr (ENABLE_DEPENDENCY_CHECK) {
231 if (isActive) {
232 GetDeps().End();
233 }
234 }
235 return res;
236 }
237
PushValue(const IValue::Ptr & value)238 ReturnError StackProperty::PushValue(const IValue::Ptr& value)
239 {
240 auto& internal = GetData();
241 if (!internal || !value || !IsValueGetCompatible(*internal, *value)) {
242 CORE_LOG_W("Incompatible value");
243 return GenericError::INCOMPATIBLE_TYPES;
244 }
245 values_.push_back(value);
246 // if it is property, see that there is no circular dependency
247 if (interface_cast<IProperty>(value)) {
248 requiresEvaluation_ = true;
249 if (!RawGetValue().GetTypeId().IsValid()) {
250 values_.pop_back();
251 return GenericError::RECURSIVE_CALL;
252 }
253 }
254 if (auto i = interface_cast<INotifyOnChange>(value)) {
255 i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
256 }
257 NotifyChange();
258 return GenericError::SUCCESS;
259 }
PopValue()260 ReturnError StackProperty::PopValue()
261 {
262 if (!values_.empty()) {
263 if (auto i = interface_cast<INotifyOnChange>(values_.back())) {
264 i->OnChanged()->RemoveHandler(uintptr_t(this));
265 }
266 values_.pop_back();
267 NotifyChange();
268 return GenericError::SUCCESS;
269 }
270 return GenericError::NOT_FOUND;
271 }
TopValue() const272 IValue::Ptr StackProperty::TopValue() const
273 {
274 return !values_.empty() ? values_.back() : nullptr;
275 }
RemoveValue(const IValue::Ptr & value)276 ReturnError StackProperty::RemoveValue(const IValue::Ptr& value)
277 {
278 size_t index = 0;
279 for (auto m = values_.rbegin(); m != values_.rend(); ++m, ++index) {
280 if (*m == value) {
281 if (auto i = interface_cast<INotifyOnChange>(*m)) {
282 i->OnChanged()->RemoveHandler(uintptr_t(this));
283 }
284 values_.erase(m.base() - 1);
285 // notify if the top-most value was removed (i.e. pop value)
286 if (index == 0) {
287 NotifyChange();
288 }
289 return GenericError::SUCCESS;
290 }
291 }
292
293 return GenericError::NOT_FOUND;
294 }
GetValues(const BASE_NS::array_view<const TypeId> & ids,bool strict) const295 BASE_NS::vector<IValue::Ptr> StackProperty::GetValues(const BASE_NS::array_view<const TypeId>& ids, bool strict) const
296 {
297 BASE_NS::vector<IValue::Ptr> ret;
298 for (auto&& v : values_) {
299 if (CheckInterfaces(interface_pointer_cast<CORE_NS::IInterface>(v), ids, strict)) {
300 ret.push_back(v);
301 }
302 }
303 return ret;
304 }
InsertModifier(IndexType pos,const IModifier::Ptr & mod)305 ReturnError StackProperty::InsertModifier(IndexType pos, const IModifier::Ptr& mod)
306 {
307 auto& internal = GetData();
308 if (!internal || !mod || !IsModifierGetCompatible(*internal, *mod)) {
309 CORE_LOG_W("Incompatible modifier");
310 return GenericError::INCOMPATIBLE_TYPES;
311 }
312 if (auto i = interface_cast<INotifyOnChange>(mod)) {
313 i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
314 }
315 IndexType i = pos < modifiers_.size() ? pos : modifiers_.size();
316 modifiers_.insert(modifiers_.begin() + i, mod);
317 NotifyChange();
318 return GenericError::SUCCESS;
319 }
RemoveModifier(IndexType pos)320 IModifier::Ptr StackProperty::RemoveModifier(IndexType pos)
321 {
322 IModifier::Ptr p;
323 if (pos < modifiers_.size()) {
324 p = modifiers_[pos];
325 modifiers_.erase(modifiers_.begin() + pos);
326 if (auto i = interface_cast<INotifyOnChange>(p)) {
327 i->OnChanged()->RemoveHandler(uintptr_t(this));
328 }
329 NotifyChange();
330 }
331 return p;
332 }
RemoveModifier(const IModifier::Ptr & mod)333 ReturnError StackProperty::RemoveModifier(const IModifier::Ptr& mod)
334 {
335 for (auto m = modifiers_.begin(); m != modifiers_.end(); ++m) {
336 if (*m == mod) {
337 if (auto i = interface_cast<INotifyOnChange>(*m)) {
338 i->OnChanged()->RemoveHandler(uintptr_t(this));
339 }
340 modifiers_.erase(m);
341 NotifyChange();
342 return GenericError::SUCCESS;
343 }
344 }
345
346 return GenericError::NOT_FOUND;
347 }
348
GetModifiers(const BASE_NS::array_view<const TypeId> & ids,bool strict) const349 BASE_NS::vector<IModifier::Ptr> StackProperty::GetModifiers(
350 const BASE_NS::array_view<const TypeId>& ids, bool strict) const
351 {
352 BASE_NS::vector<IModifier::Ptr> ret;
353 for (auto&& m : modifiers_) {
354 if (CheckInterfaces(interface_pointer_cast<CORE_NS::IInterface>(m), ids, strict)) {
355 ret.push_back(m);
356 }
357 }
358 return ret;
359 }
SetDefaultValue(const IAny & value)360 AnyReturnValue StackProperty::SetDefaultValue(const IAny& value)
361 {
362 CORE_ASSERT_MSG(defaultValue_, "SetInternalAny not called");
363 AnyReturnValue res = defaultValue_->CopyFrom(value);
364 if (res && values_.empty()) {
365 NotifyChange();
366 }
367 return res;
368 }
GetDefaultValue() const369 const IAny& StackProperty::GetDefaultValue() const
370 {
371 CORE_ASSERT_MSG(defaultValue_, "SetInternalAny not called");
372 return *defaultValue_;
373 }
SetInternalAny(IAny::Ptr any)374 AnyReturnValue StackProperty::SetInternalAny(IAny::Ptr any)
375 {
376 auto res = Super::SetInternalAny(any);
377 if (res) {
378 defaultValue_ = any->Clone(true);
379 if (auto i = interface_cast<INotifyOnChange>(defaultValue_)) {
380 i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
381 }
382 currentValue_ = defaultValue_->Clone(true);
383 requiresEvaluation_ = true;
384 values_.clear();
385 modifiers_.clear();
386 }
387 return res;
388 }
NotifyChange() const389 void StackProperty::NotifyChange() const
390 {
391 requiresEvaluation_ = true;
392 CallOnChanged(evaluating_);
393 }
394 template<typename Vec>
ProcessResetables(Vec & vec)395 bool StackProperty::ProcessResetables(Vec& vec)
396 {
397 for (int i = int(vec.size()) - 1; i >= 0; --i) {
398 ResetResult res = ResetResult::RESET_REMOVE_ME;
399 if (auto rable = interface_cast<IStackResetable>(vec[i])) {
400 InterfaceSharedLock lock { rable };
401 res = rable->ProcessOnReset(*defaultValue_);
402 }
403 if (res & RESET_REMOVE_ME) {
404 vec.erase(vec.begin() + i);
405 }
406 if (res & RESET_STOP) {
407 return false;
408 }
409 }
410 return true;
411 }
ResetValue()412 void StackProperty::ResetValue()
413 {
414 ProcessResetables(modifiers_);
415 ProcessResetables(values_);
416
417 // reset the currentValue_ and internal value so we don't accidentally keep any shared_ptrs alive
418 currentValue_ = defaultValue_->Clone(false);
419 SetInternalValue(*currentValue_);
420 SetDefaultValueFlag(true);
421 NotifyChange();
422 }
RemoveAll()423 void StackProperty::RemoveAll()
424 {
425 values_.clear();
426 modifiers_.clear();
427 // reset the currentValue_ and internal value so we don't accidentally keep any shared_ptrs alive
428 currentValue_ = defaultValue_->Clone(false);
429 SetInternalValue(*currentValue_);
430 SetDefaultValueFlag(true);
431 NotifyChange();
432 }
Export(IExportContext & c) const433 ReturnError StackProperty::Export(IExportContext& c) const
434 {
435 return Serializer(c) & NamedValue("defaultValue", defaultValue_) & NamedValue("values", values_) &
436 NamedValue("modifiers", modifiers_);
437 }
Import(IImportContext & c)438 ReturnError StackProperty::Import(IImportContext& c)
439 {
440 CleanUp();
441 BASE_NS::vector<SharedPtrIInterface> values;
442 BASE_NS::vector<SharedPtrIInterface> modifiers;
443 Serializer ser(c);
444 ser& NamedValue("defaultValue", defaultValue_) & NamedValue("values", values) & NamedValue("modifiers", modifiers);
445 if (ser) {
446 bool def = true;
447 if (!defaultValue_) {
448 return GenericError::FAIL;
449 }
450 if (auto i = interface_cast<INotifyOnChange>(defaultValue_)) {
451 i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
452 }
453 if (auto res = Super::SetInternalAny(defaultValue_->Clone(false))) {
454 currentValue_ = defaultValue_->Clone(true);
455 requiresEvaluation_ = true;
456 }
457 for (auto&& i : values) {
458 if (auto v = interface_pointer_cast<IValue>(i)) {
459 if (auto i = interface_cast<INotifyOnChange>(v)) {
460 i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
461 }
462 values_.push_back(BASE_NS::move(v));
463 def = false;
464 }
465 }
466 for (auto&& i : modifiers) {
467 if (auto v = interface_pointer_cast<IModifier>(i)) {
468 if (auto i = interface_cast<INotifyOnChange>(v)) {
469 i->OnChanged()->AddHandler(onChangedCallback_, uintptr_t(this));
470 }
471 modifiers_.push_back(BASE_NS::move(v));
472 }
473 }
474 SetDefaultValueFlag(def);
475 }
476 return ser;
477 }
478
IsDefaultValue() const479 bool StackProperty::IsDefaultValue() const
480 {
481 return HasDefaultValueFlag();
482 }
483
484 } // namespace Internal
485 META_END_NAMESPACE()
486