* 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"
#if defined(META_USE_SHARED_MUTEX)
#include <shared_mutex>
#else
#include <mutex>
#endif
#include <meta/interface/animation/builtin_animations.h>
META_BEGIN_NAMESPACE()
using CORE_NS::MutexHandle;
using CORE_NS::MutexType;
#if defined(META_USE_SHARED_MUTEX)
using InternalMutexType = std::shared_mutex;
#else
using InternalMutexType = std::mutex;
#endif
constexpr bool USE_IN_PLACE_MUTEX =
sizeof(InternalMutexType) <= sizeof(MutexHandle::storage) && alignof(InternalMutexType) <= alignof(MutexHandle);
static void CreateMutex(MutexType, MutexHandle& handle)
{
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);
}
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()