/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "meta_object_lib.h" #include <shared_mutex> #include <meta/interface/animation/builtin_animations.h> META_BEGIN_NAMESPACE() using CORE_NS::MutexHandle; using CORE_NS::MutexType; #if defined(__ANDROID__) using InternalMutexType = std::mutex; #else // std::mutex on vc2017 is 80 bytes and much slower than std::shared_mutex using InternalMutexType = std::shared_mutex; #endif constexpr bool USE_IN_PLACE_MUTEX = sizeof(InternalMutexType) <= sizeof(MutexHandle::storage) && alignof(InternalMutexType) <= alignof(MutexHandle); static void CreateMutex(MutexType, MutexHandle& handle) { // do we have suitable storage for constructing mutex in-place if constexpr (USE_IN_PLACE_MUTEX) { new (handle.storage) InternalMutexType; } else { handle.ptr = new InternalMutexType; } } static void DestroyMutex(MutexHandle& handle) { if constexpr (USE_IN_PLACE_MUTEX) { static_cast<InternalMutexType*>(static_cast<void*>(handle.storage))->~InternalMutexType(); } else { delete static_cast<InternalMutexType*>(handle.ptr); } } static bool LockMutex(MutexHandle& handle) { if constexpr (USE_IN_PLACE_MUTEX) { static_cast<InternalMutexType*>(static_cast<void*>(handle.storage))->lock(); } else { static_cast<InternalMutexType*>(handle.ptr)->lock(); } return true; } static bool UnlockMutex(MutexHandle& handle) { if constexpr (USE_IN_PLACE_MUTEX) { static_cast<InternalMutexType*>(static_cast<void*>(handle.storage))->unlock(); } else { static_cast<InternalMutexType*>(handle.ptr)->unlock(); } return true; } static uint64_t GetThreadId() { thread_local const char variable {}; return reinterpret_cast<uint64_t>(&variable); } namespace Internal { void RegisterEntities(IObjectRegistry& registry); void UnRegisterEntities(IObjectRegistry& registry); void RegisterValueSerializers(IObjectRegistry& registry); void UnRegisterValueSerializers(IObjectRegistry& registry); void RegisterAnys(IObjectRegistry& registry); void UnRegisterAnys(IObjectRegistry& registry); void RegisterEngineTypes(IObjectRegistry& registry); void UnRegisterEngineTypes(IObjectRegistry& registry); } // namespace Internal const CORE_NS::IInterface* MetaObjectLib::GetInterface(const BASE_NS::Uid& uid) const { if (uid == IMetaObjectLib::UID) { return this; } if (uid == CORE_NS::IInterface::UID) { return this; } return nullptr; } CORE_NS::IInterface* MetaObjectLib::GetInterface(const BASE_NS::Uid& uid) { const auto* p = this; return const_cast<CORE_NS::IInterface*>(p->MetaObjectLib::GetInterface(uid)); } MetaObjectLib::MetaObjectLib() : sapi_ { { CreateMutex, DestroyMutex, LockMutex, UnlockMutex }, GetThreadId } { if (USE_IN_PLACE_MUTEX) { CORE_LOG_D("Using in-place mutex"); } else { CORE_LOG_D("Not using in-place mutex"); } } void MetaObjectLib::Initialize() { registry_ = new ObjectRegistry; Internal::RegisterAnys(*registry_); Internal::RegisterEntities(*registry_); Internal::RegisterValueSerializers(*registry_); Internal::RegisterEngineTypes(*registry_); } void MetaObjectLib::Uninitialize() { Internal::UnRegisterEngineTypes(*registry_); Internal::UnRegisterValueSerializers(*registry_); Internal::UnRegisterEntities(*registry_); Internal::UnRegisterAnys(*registry_); } MetaObjectLib::~MetaObjectLib() { animationController_.reset(); registry_->Purge(); delete registry_; } IObjectRegistry& MetaObjectLib::GetObjectRegistry() const { return *registry_; } ITaskQueueRegistry& MetaObjectLib::GetTaskQueueRegistry() const { return *static_cast<ITaskQueueRegistry*>(registry_); } IAnimationController::Ptr MetaObjectLib::GetAnimationController() const { std::call_once(animInit_, [&] { auto iregistry = static_cast<IObjectRegistry*>(registry_); animationController_ = iregistry->Create<IAnimationController>(ClassId::AnimationController); }); return animationController_; } const CORE_NS::SyncApi& MetaObjectLib::GetSyncApi() const { return sapi_; } META_END_NAMESPACE()