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 <new> 17 18#include <base/containers/array_view.h> 19#include <base/containers/iterator.h> 20#include <base/namespace.h> 21#include <core/log.h> 22#include <core/namespace.h> 23#include <core/property/intf_property_api.h> 24#include <core/property/intf_property_handle.h> 25#include <core/property/property.h> 26#include <core/property_tools/property_api_impl.h> 27 28CORE_BEGIN_NAMESPACE() 29template<typename BlockType> 30PropertyApiImpl<BlockType>::PropertyApiImpl() = default; 31 32template<typename BlockType> 33PropertyApiImpl<BlockType>::PropertyApiImpl(BlockType* data, BASE_NS::array_view<const Property> aProps) 34 : data_(data), componentMetadata_(aProps) 35{ 36 // Create a typeid by hashing the metadata information. 37 typeHash_ = 0; 38 for (auto& t : aProps) { 39 BASE_NS::HashCombine(typeHash_, t.offset); 40 BASE_NS::HashCombine(typeHash_, t.count); 41 BASE_NS::HashCombine(typeHash_, t.type.compareHash); 42 BASE_NS::HashCombine(typeHash_, t.type.typeHash); 43 BASE_NS::HashCombine(typeHash_, t.hash); 44 BASE_NS::HashCombine(typeHash_, t.size); 45 } 46} 47 48template<typename BlockType> 49size_t PropertyApiImpl<BlockType>::PropertyCount() const 50{ 51 if (owner_) { 52 return owner_->PropertyCount(); 53 } 54 return componentMetadata_.size(); 55} 56 57// Metadata for property 58template<typename BlockType> 59const Property* PropertyApiImpl<BlockType>::MetaData(size_t aIndex) const 60{ 61 if (owner_) { 62 return owner_->MetaData(aIndex); 63 } 64 return &componentMetadata_[aIndex]; 65} 66 67// Metadata for properties 68template<typename BlockType> 69BASE_NS::array_view<const Property> PropertyApiImpl<BlockType>::MetaData() const 70{ 71 if (owner_) { 72 return owner_->MetaData(); 73 } 74 return componentMetadata_; 75} 76 77template<typename BlockType> 78IPropertyHandle* PropertyApiImpl<BlockType>::Create() const 79{ 80 auto ret = new PropertyApiImpl<BlockType>(); 81 ret->owner_ = Owner(); 82 ret->typeHash_ = Type(); 83 ret->data_ = new BlockType(); 84 return ret; 85} 86 87template<typename BlockType> 88IPropertyHandle* PropertyApiImpl<BlockType>::Clone(const IPropertyHandle* src) const 89{ 90 if (src->Owner() == this) { 91 auto* h = static_cast<const PropertyApiImpl<BlockType>*>(src); 92 auto* ret = new PropertyApiImpl<BlockType>(); 93 ret->owner_ = Owner(); 94 ret->typeHash_ = Type(); 95 ret->data_ = new BlockType(); 96 *ret->data_ = *h->data_; 97 return ret; 98 } 99 return nullptr; 100} 101 102template<typename BlockType> 103void PropertyApiImpl<BlockType>::Release(IPropertyHandle* dst) const 104{ 105 if (dst) { 106 if (dst->Owner() == Owner()) { 107 // we can only destroy things we "own" (know) 108 auto* handle = static_cast<PropertyApiImpl<BlockType>*>(dst); 109 if (handle->owner_) { 110 // and only the ones that own the data.. 111 delete handle; 112 } 113 } 114 } 115} 116 117template<typename BlockType> 118uint32_t PropertyApiImpl<BlockType>::GetGeneration() const 119{ 120 return generationCount_; 121} 122 123template<typename BlockType> 124IPropertyHandle* PropertyApiImpl<BlockType>::GetData() 125{ 126 return this; 127} 128 129template<typename BlockType> 130const IPropertyHandle* PropertyApiImpl<BlockType>::GetData() const 131{ 132 return this; 133} 134 135template<typename BlockType> 136const IPropertyApi* PropertyApiImpl<BlockType>::Owner() const 137{ 138 if (owner_) { 139 return owner_; 140 } 141 return this; 142} 143 144template<typename BlockType> 145size_t PropertyApiImpl<BlockType>::Size() const 146{ 147 return sizeof(BlockType); 148} 149 150template<typename BlockType> 151const void* PropertyApiImpl<BlockType>::RLock() const 152{ 153#ifndef NDEBUG 154 CORE_ASSERT(!wLocked_); 155 rLocked_++; 156#endif 157 return data_; 158} 159 160template<typename BlockType> 161void PropertyApiImpl<BlockType>::RUnlock() const 162{ 163#ifndef NDEBUG 164 CORE_ASSERT(rLocked_ > 0); 165 rLocked_--; 166#endif 167} 168 169template<typename BlockType> 170void* PropertyApiImpl<BlockType>::WLock() 171{ 172#ifndef NDEBUG 173 CORE_ASSERT(rLocked_ <= 1 && !wLocked_); 174 wLocked_ = true; 175#endif 176 return data_; 177} 178 179template<typename BlockType> 180void PropertyApiImpl<BlockType>::WUnlock() 181{ 182#ifndef NDEBUG 183 CORE_ASSERT(wLocked_); 184 wLocked_ = false; 185#endif 186 generationCount_++; 187} 188 189template<typename BlockType> 190uint64_t PropertyApiImpl<BlockType>::Type() const 191{ 192 return typeHash_; 193} 194 195template<> 196inline size_t PropertyApiImpl<void>::Size() const 197{ 198 return 0; 199} 200 201template<> 202inline IPropertyHandle* PropertyApiImpl<void>::Create() const 203{ 204 auto ret = new PropertyApiImpl<void>(); 205 ret->owner_ = owner_; 206 ret->data_ = nullptr; 207 return ret; 208} 209 210template<> 211inline IPropertyHandle* PropertyApiImpl<void>::Clone(const IPropertyHandle* src) const 212{ 213 if (src->Owner() == this) { 214 auto* ret = new PropertyApiImpl<void>(); 215 ret->owner_ = owner_; 216 return ret; 217 } 218 return nullptr; 219} 220 221template<> 222inline void PropertyApiImpl<void>::Release(IPropertyHandle* dst) const 223{ 224 if (dst) { 225 if (dst->Owner() == this) { 226 // we can only destroy things we "own" (know) 227 auto* handle = static_cast<PropertyApiImpl<void>*>(dst); 228 delete handle; 229 } 230 } 231} 232 233CORE_END_NAMESPACE() 234