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 
16 #include "meta_object_lib.h"
17 
18 #include <shared_mutex>
19 
20 #include <meta/interface/animation/builtin_animations.h>
21 
22 META_BEGIN_NAMESPACE()
23 
24 using CORE_NS::MutexHandle;
25 using CORE_NS::MutexType;
26 
27 #if defined(__ANDROID__)
28 using InternalMutexType = std::mutex;
29 #else
30 // std::mutex on vc2017 is 80 bytes and much slower than std::shared_mutex
31 using InternalMutexType = std::shared_mutex;
32 #endif
33 
34 constexpr bool USE_IN_PLACE_MUTEX =
35     sizeof(InternalMutexType) <= sizeof(MutexHandle::storage) && alignof(InternalMutexType) <= alignof(MutexHandle);
36 
CreateMutex(MutexType,MutexHandle & handle)37 static void CreateMutex(MutexType, MutexHandle& handle)
38 {
39     // do we have suitable storage for constructing mutex in-place
40     if constexpr (USE_IN_PLACE_MUTEX) {
41         new (handle.storage) InternalMutexType;
42     } else {
43         handle.ptr = new InternalMutexType;
44     }
45 }
46 
DestroyMutex(MutexHandle & handle)47 static void DestroyMutex(MutexHandle& handle)
48 {
49     if constexpr (USE_IN_PLACE_MUTEX) {
50         static_cast<InternalMutexType*>(static_cast<void*>(handle.storage))->~InternalMutexType();
51     } else {
52         delete static_cast<InternalMutexType*>(handle.ptr);
53     }
54 }
55 
LockMutex(MutexHandle & handle)56 static bool LockMutex(MutexHandle& handle)
57 {
58     if constexpr (USE_IN_PLACE_MUTEX) {
59         static_cast<InternalMutexType*>(static_cast<void*>(handle.storage))->lock();
60     } else {
61         static_cast<InternalMutexType*>(handle.ptr)->lock();
62     }
63     return true;
64 }
65 
UnlockMutex(MutexHandle & handle)66 static bool UnlockMutex(MutexHandle& handle)
67 {
68     if constexpr (USE_IN_PLACE_MUTEX) {
69         static_cast<InternalMutexType*>(static_cast<void*>(handle.storage))->unlock();
70     } else {
71         static_cast<InternalMutexType*>(handle.ptr)->unlock();
72     }
73     return true;
74 }
75 
GetThreadId()76 static uint64_t GetThreadId()
77 {
78     thread_local const char variable {};
79     return reinterpret_cast<uint64_t>(&variable);
80 }
81 
82 namespace Internal {
83 void RegisterEntities(IObjectRegistry& registry);
84 void UnRegisterEntities(IObjectRegistry& registry);
85 void RegisterValueSerializers(IObjectRegistry& registry);
86 void UnRegisterValueSerializers(IObjectRegistry& registry);
87 void RegisterAnys(IObjectRegistry& registry);
88 void UnRegisterAnys(IObjectRegistry& registry);
89 void RegisterEngineTypes(IObjectRegistry& registry);
90 void UnRegisterEngineTypes(IObjectRegistry& registry);
91 } // namespace Internal
92 
GetInterface(const BASE_NS::Uid & uid) const93 const CORE_NS::IInterface* MetaObjectLib::GetInterface(const BASE_NS::Uid& uid) const
94 {
95     if (uid == IMetaObjectLib::UID) {
96         return this;
97     }
98     if (uid == CORE_NS::IInterface::UID) {
99         return this;
100     }
101     return nullptr;
102 }
103 
GetInterface(const BASE_NS::Uid & uid)104 CORE_NS::IInterface* MetaObjectLib::GetInterface(const BASE_NS::Uid& uid)
105 {
106     const auto* p = this;
107     return const_cast<CORE_NS::IInterface*>(p->MetaObjectLib::GetInterface(uid));
108 }
109 
MetaObjectLib()110 MetaObjectLib::MetaObjectLib()
111     : sapi_ { { CreateMutex, DestroyMutex, LockMutex, UnlockMutex }, GetThreadId }
112 {
113     if (USE_IN_PLACE_MUTEX) {
114         CORE_LOG_D("Using in-place mutex");
115     } else {
116         CORE_LOG_D("Not using in-place mutex");
117     }
118 }
119 
Initialize()120 void MetaObjectLib::Initialize()
121 {
122     registry_ = new ObjectRegistry;
123     Internal::RegisterAnys(*registry_);
124     Internal::RegisterEntities(*registry_);
125     Internal::RegisterValueSerializers(*registry_);
126     Internal::RegisterEngineTypes(*registry_);
127 }
128 
Uninitialize()129 void MetaObjectLib::Uninitialize()
130 {
131     Internal::UnRegisterEngineTypes(*registry_);
132     Internal::UnRegisterValueSerializers(*registry_);
133     Internal::UnRegisterEntities(*registry_);
134     Internal::UnRegisterAnys(*registry_);
135 }
136 
~MetaObjectLib()137 MetaObjectLib::~MetaObjectLib()
138 {
139     animationController_.reset();
140     registry_->Purge();
141     delete registry_;
142 }
143 
GetObjectRegistry() const144 IObjectRegistry& MetaObjectLib::GetObjectRegistry() const
145 {
146     return *registry_;
147 }
148 
GetTaskQueueRegistry() const149 ITaskQueueRegistry& MetaObjectLib::GetTaskQueueRegistry() const
150 {
151     return *static_cast<ITaskQueueRegistry*>(registry_);
152 }
153 
GetAnimationController() const154 IAnimationController::Ptr MetaObjectLib::GetAnimationController() const
155 {
156     std::call_once(animInit_, [&] {
157         auto iregistry = static_cast<IObjectRegistry*>(registry_);
158         animationController_ = iregistry->Create<IAnimationController>(ClassId::AnimationController);
159     });
160     return animationController_;
161 }
162 
GetSyncApi() const163 const CORE_NS::SyncApi& MetaObjectLib::GetSyncApi() const
164 {
165     return sapi_;
166 }
167 
168 META_END_NAMESPACE()
169