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 "object_registry.h"
17
18 #include <chrono>
19
20 #include <base/containers/fixed_string.h>
21 #include <base/util/compile_time_hashes.h>
22 #include <base/util/uid_util.h>
23
24 #include <meta/interface/animation/builtin_animations.h>
25 #include <meta/interface/intf_derived.h>
26
27 #include "any.h"
28 #include "call_context.h"
29 #include "metadata.h"
30 #include "property/bind.h"
31 #include "property/stack_property.h"
32 #include "random.h"
33
34 #define OBJ_REG_LOG(...)
35
36 /*
37 Notes:
38 * Currently Unregistering object and creating it at the same time can cause the pointer ObjectTypeInfo still
39 be used after the Unregister function returns.
40 * Same issue applies to creating and unregistering property.
41 */
42
43 META_BEGIN_NAMESPACE()
44
45 const size_t DISPOSAL_THRESHOLD = 100;
46
GenerateInstanceId(uint64_t random)47 static BASE_NS::Uid GenerateInstanceId(uint64_t random)
48 {
49 // NOTE: instance uid:s are generated from 64 bit random number and 64 bit timestamp
50 auto elapsed = std::chrono::high_resolution_clock::now();
51 auto high = std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed.time_since_epoch()).count();
52
53 BASE_NS::Uid uid;
54 uid.data[0] = high;
55 uid.data[1] = random;
56 return uid;
57 }
58
ObjectRegistry()59 ObjectRegistry::ObjectRegistry() : random_(CreateXoroshiro128(BASE_NS::FNV1aHash("ToolKitObjectRegistry"))) {}
60
~ObjectRegistry()61 ObjectRegistry::~ObjectRegistry()
62 {
63 queues_.clear();
64 defaultContext_.reset();
65 classRegistry_.Clear();
66 // Just for sanity.
67 GC();
68 // And to make sure all "objects" are unregistered. (we have some that never un-register)
69 // doing it one at a time, because unregister will modify the list..
70 bool first = true;
71 auto& pluginRegistry = CORE_NS::GetPluginRegister();
72 for (;;) {
73 const auto& types = pluginRegistry.GetTypeInfos(ObjectTypeInfo::UID);
74 if (types.empty()) {
75 break;
76 }
77 auto object = static_cast<const ObjectTypeInfo* const>(types[0]);
78 if (first) {
79 CORE_LOG_F("Object classes not unregistered before object registry death. (force unregister)");
80 first = false;
81 }
82 auto& classInfo = object->GetFactory()->GetClassInfo();
83 CORE_LOG_F(
84 "Name: [%s] ClassId [%s]", BASE_NS::string(classInfo.Name()).c_str(), classInfo.Id().ToString().c_str());
85 pluginRegistry.UnregisterTypeInfo(*types[0]);
86 }
87 }
88
GetClassRegistry()89 IClassRegistry& ObjectRegistry::GetClassRegistry()
90 {
91 return classRegistry_;
92 }
93
RegisterToPluginRegistry(const ObjectTypeInfo & info)94 static void RegisterToPluginRegistry(const ObjectTypeInfo& info)
95 {
96 auto& pluginRegistry = CORE_NS::GetPluginRegister();
97 const auto& types = pluginRegistry.GetTypeInfos(ObjectTypeInfo::UID);
98 for (auto it = types.begin(); it != types.end(); it++) {
99 auto object = static_cast<const ObjectTypeInfo* const>(*it);
100 if (*object == info) {
101 return;
102 }
103 }
104 pluginRegistry.RegisterTypeInfo(info);
105 }
106
UnregisterFromPluginRegistry(const BASE_NS::Uid & uid)107 static void UnregisterFromPluginRegistry(const BASE_NS::Uid& uid)
108 {
109 auto& pluginRegistry = CORE_NS::GetPluginRegister();
110 const auto& types = pluginRegistry.GetTypeInfos(ObjectTypeInfo::UID);
111 for (auto it = types.begin(); it != types.end(); it++) {
112 auto object = static_cast<const ObjectTypeInfo* const>(*it);
113 if (object->GetFactory()->GetClassInfo().Id() == ObjectId(uid)) {
114 pluginRegistry.UnregisterTypeInfo(**it);
115 break;
116 }
117 }
118 }
119
RegisterObjectType(const IClassInfo::Ptr & classInfo)120 bool ObjectRegistry::RegisterObjectType(const IClassInfo::Ptr& classInfo)
121 {
122 if (!classInfo) {
123 return false;
124 }
125 const auto factory = interface_pointer_cast<IObjectFactory>(classInfo);
126 if (!factory) {
127 CORE_LOG_E("ObjectRegistry: The class (%s) being registered does not provide object factory",
128 classInfo->GetClassInfo().Name().data());
129 }
130 if (!classRegistry_.Register(factory)) {
131 return false;
132 }
133
134 // Construct dummy object of that type to get the static metadata initialised
135 BASE_NS::vector<IObject::Ptr> classes;
136 auto res = CreateInternal(factory->GetClassInfo().Id().ToUid(), classes);
137 if (res.successful && !classes.empty()) {
138 // for now we need to set the super classes to safely destroy some objects, using dummy instance id
139 SetObjectInstanceIds(classes, BASE_NS::Uid {});
140 } else {
141 CORE_LOG_W("Failed to create object when generating static metadata [uid=%s]",
142 BASE_NS::to_string(factory->GetClassInfo().Id().ToUid()).c_str());
143 }
144 return true;
145 }
146
UnregisterObjectType(const IClassInfo::Ptr & classInfo)147 bool ObjectRegistry::UnregisterObjectType(const IClassInfo::Ptr& classInfo)
148 {
149 if (const auto factory = interface_pointer_cast<IObjectFactory>(classInfo)) {
150 return classRegistry_.Unregister(factory);
151 }
152 return false;
153 }
154
GetClassName(BASE_NS::Uid uid) const155 BASE_NS::string ObjectRegistry::GetClassName(BASE_NS::Uid uid) const
156 {
157 return classRegistry_.GetClassName(uid);
158 }
159
CreateInternal(BASE_NS::Uid uid,BASE_NS::vector<IObject::Ptr> & classes) const160 ObjectRegistry::CreateResult ObjectRegistry::CreateInternal(
161 BASE_NS::Uid uid, BASE_NS::vector<IObject::Ptr>& classes) const
162 {
163 IObject::Ptr obj;
164 ClassInfo info;
165 if (auto fac = classRegistry_.GetObjectFactory(uid)) {
166 obj = fac->CreateInstance();
167 if (obj) {
168 info = fac->GetClassInfo();
169 return CreateResult { ConstructObjectInternal(obj, classes), info.category, info.IsSingleton() };
170 }
171 }
172 return { false, 0, false };
173 }
174
ConstructObjectInternal(const IObject::Ptr & obj,BASE_NS::vector<IObject::Ptr> & classes) const175 bool ObjectRegistry::ConstructObjectInternal(const IObject::Ptr& obj, BASE_NS::vector<IObject::Ptr>& classes) const
176 {
177 classes.push_back(obj);
178 if (auto agr = obj->GetInterface<IDerived>()) {
179 auto superUid = agr->GetSuperClassUid();
180 if (superUid != BASE_NS::Uid {}) {
181 OBJ_REG_LOG("\tCreate super of %s", GetClassName(superUid).c_str());
182 auto super = CreateInternal(superUid, classes);
183 if (!super.successful) {
184 // failed to create super class.
185 CORE_LOG_F("Could not create the super class [uid=%s]", BASE_NS::to_string(superUid).c_str());
186 return false;
187 }
188 }
189 }
190 return true;
191 }
192
SetObjectInstanceIds(const BASE_NS::vector<IObject::Ptr> & classes,InstanceId instid) const193 void ObjectRegistry::SetObjectInstanceIds(const BASE_NS::vector<IObject::Ptr>& classes, InstanceId instid) const
194 {
195 IObject::Ptr obj = classes.front();
196 IObject::Ptr base;
197
198 // Prepare object hierarchy for building by setting instance ids and super objects
199 for (auto it = classes.rbegin(); it != classes.rend(); ++it) {
200 if (auto o = (*it)->GetInterface<ILifecycle>()) {
201 o->SetInstanceId(instid);
202 }
203 if (auto der = (*it)->GetInterface<IDerived>()) {
204 if (base) {
205 OBJ_REG_LOG("\tAssigning instance of %s as super to %s", BASE_NS::string(base->GetClassName()).c_str(),
206 BASE_NS::string((*it)->GetClassName()).c_str());
207 }
208 der->SetSuperInstance(obj, base);
209 }
210 base = *it;
211 }
212 }
213
BuildObject(const BASE_NS::vector<IObject::Ptr> & classes,const IMetadata::Ptr & data) const214 bool ObjectRegistry::BuildObject(const BASE_NS::vector<IObject::Ptr>& classes, const IMetadata::Ptr& data) const
215 {
216 if (classes.empty()) {
217 return false;
218 }
219 IObject::Ptr obj = classes.front();
220 IMetadata::Ptr meta = ConstructMetadata();
221
222 // Set metadata first so that one can use IMetadata via GetSelf in the non-top classes' Build
223 for (auto it = classes.rbegin(); it != classes.rend(); ++it) {
224 if (auto i = (*it)->GetInterface<IMetadataInternal>()) {
225 i->SetMetadata(meta);
226 }
227 }
228 // call build for the object hierarchy
229 for (auto it = classes.rbegin(); it != classes.rend(); ++it) {
230 if (auto ctor = (*it)->GetInterface<ILifecycle>()) {
231 OBJ_REG_LOG("\tBuilding %s", BASE_NS::string((*it)->GetClassName()).c_str());
232 if (!ctor->Build(data)) {
233 return false;
234 }
235 }
236 }
237 return true;
238 }
239
Create(ObjectId uid,const CreateInfo & createInfo,const IMetadata::Ptr & data) const240 IObject::Ptr ObjectRegistry::Create(ObjectId uid, const CreateInfo& createInfo, const IMetadata::Ptr& data) const
241 {
242 CheckGC();
243
244 auto instid = createInfo.instanceId;
245
246 if (instid == BASE_NS::Uid {}) {
247 std::unique_lock lock { mutex_ };
248 if (auto so = FindSingleton(uid.ToUid())) {
249 return so;
250 }
251 instid = GenerateInstanceId(random_->GetRandom());
252 } else {
253 std::shared_lock lock { mutex_ };
254 if (auto so = FindSingleton(uid.ToUid())) {
255 return so;
256 }
257 // make sure that an object with specified instanceid does not exist already.
258 auto it = instancesByUid_.find(instid);
259 if (it != instancesByUid_.end() && !it->second.ptr.expired()) {
260 CORE_LOG_F("Object with instance id %s already exists.", instid.ToString().c_str());
261 return {};
262 }
263 }
264 OBJ_REG_LOG("Create instance of %s {instance id %s}", GetClassName(uid).c_str(), instid.ToString().c_str());
265 BASE_NS::vector<IObject::Ptr> classes;
266 auto t = CreateInternal(uid.ToUid(), classes);
267 if (t.successful && !classes.empty()) {
268 if (PostCreate(uid.ToUid(), instid.ToUid(), t, createInfo, classes, data)) {
269 return classes.front();
270 }
271 }
272
273 CORE_LOG_F("Could not create instance of %s", GetClassName(uid.ToUid()).c_str());
274 return nullptr;
275 }
276
PostCreate(const BASE_NS::Uid & uid,InstanceId instid,const CreateResult & t,const CreateInfo & createInfo,const BASE_NS::vector<IObject::Ptr> & classes,const IMetadata::Ptr & data) const277 bool ObjectRegistry::PostCreate(const BASE_NS::Uid& uid, InstanceId instid, const CreateResult& t,
278 const CreateInfo& createInfo, const BASE_NS::vector<IObject::Ptr>& classes, const IMetadata::Ptr& data) const
279 {
280 SetObjectInstanceIds(classes, instid);
281
282 if (!BuildObject(classes, data)) {
283 CORE_LOG_F("Failed to build object (%s).", GetClassName(uid).c_str());
284 return false;
285 }
286
287 std::unique_lock lock { mutex_ };
288 auto& i = instancesByUid_[instid];
289 if (!i.ptr.expired()) {
290 // seems someone beat us to it
291 CORE_LOG_F("Object with instance id %s already exists.", instid.ToString().c_str());
292 return false;
293 }
294 i = ObjectInstance { classes.front(), t.category };
295
296 if (t.singleton) {
297 singletons_[uid] = classes.front(); // Store singleton weakref
298 }
299 if (createInfo.isGloballyAvailable) {
300 CORE_LOG_D("Registering global object: %s [%s]", GetClassName(uid).c_str(), instid.ToString().c_str());
301 globalObjects_[instid] = classes.front();
302 }
303 return true;
304 }
305
Create(ObjectId uid,const CreateInfo & createInfo) const306 IObject::Ptr ObjectRegistry::Create(ObjectId uid, const CreateInfo& createInfo) const
307 {
308 return Create(uid, createInfo, nullptr);
309 }
310
Create(const META_NS::ClassInfo & info,const CreateInfo & createInfo) const311 IObject::Ptr ObjectRegistry::Create(const META_NS::ClassInfo& info, const CreateInfo& createInfo) const
312 {
313 return Create(info.Id(), createInfo);
314 }
315
GetAllCategories() const316 BASE_NS::vector<ObjectCategoryItem> ObjectRegistry::GetAllCategories() const
317 {
318 static const BASE_NS::vector<ObjectCategoryItem> items = { { ObjectCategoryBits::WIDGET, "Widgets" },
319 { ObjectCategoryBits::ANIMATION, "Animations" }, { ObjectCategoryBits::LAYOUT, "Layouts" },
320 { ObjectCategoryBits::CURVE, "Curves" }, { ObjectCategoryBits::SHAPE, "Shapes" },
321 { ObjectCategoryBits::CONTAINER, "Containers" }, { ObjectCategoryBits::INTERNAL, "Internals" },
322 { ObjectCategoryBits::APPLICATION, "Application specifics" },
323 { ObjectCategoryBits::ANIMATION_MODIFIER, "Animation modifier" },
324 { ObjectCategoryBits::NO_CATEGORY, "Not categorized" } };
325 return items;
326 }
327
GetObjectFactory(const ObjectId & uid) const328 IObjectFactory::ConstPtr ObjectRegistry::GetObjectFactory(const ObjectId& uid) const
329 {
330 std::shared_lock lock { mutex_ };
331 return classRegistry_.GetObjectFactory(uid.ToUid());
332 }
333
GetAllTypes(ObjectCategoryBits category,bool strict,bool excludeDeprecated) const334 BASE_NS::vector<IClassInfo::ConstPtr> ObjectRegistry::GetAllTypes(
335 ObjectCategoryBits category, bool strict, bool excludeDeprecated) const
336 {
337 std::shared_lock lock { mutex_ };
338 return classRegistry_.GetAllTypes(category, strict, excludeDeprecated);
339 }
340
CheckGC() const341 void ObjectRegistry::CheckGC() const
342 {
343 if (purgeCounter_ > DISPOSAL_THRESHOLD && disposalInProgress_.test_and_set()) {
344 {
345 std::unique_lock lock { disposalMutex_ };
346 disposalsStorage_.swap(disposals_);
347 purgeCounter_ = 0;
348 }
349 DoDisposal(disposalsStorage_);
350 disposalsStorage_.clear();
351 disposalInProgress_.clear();
352 }
353 }
354
GC() const355 void ObjectRegistry::GC() const
356 {
357 for (auto it = instancesByUid_.begin(); it != instancesByUid_.end();) {
358 if (it->second.ptr.expired()) {
359 it = instancesByUid_.erase(it);
360 } else {
361 ++it;
362 }
363 }
364 for (auto it = singletons_.begin(); it != singletons_.end();) {
365 if (it->second.expired()) {
366 it = singletons_.erase(it);
367 } else {
368 ++it;
369 }
370 }
371 for (auto it = globalObjects_.begin(); it != globalObjects_.end();) {
372 if (it->second.expired()) {
373 it = globalObjects_.erase(it);
374 } else {
375 ++it;
376 }
377 }
378 }
379
Purge()380 void ObjectRegistry::Purge()
381 {
382 std::unique_lock lock { mutex_ };
383 GC();
384 }
385
DoDisposal(const BASE_NS::vector<InstanceId> & uids) const386 void ObjectRegistry::DoDisposal(const BASE_NS::vector<InstanceId>& uids) const
387 {
388 std::unique_lock lock { mutex_ };
389 for (auto&& v : uids) {
390 auto it = instancesByUid_.find(v);
391 if (it != instancesByUid_.end()) {
392 instancesByUid_.erase(it);
393 auto it = singletons_.find(v);
394 if (it != singletons_.end()) {
395 singletons_.erase(it);
396 }
397 }
398 }
399 }
400
DisposeObject(const InstanceId & uid) const401 void ObjectRegistry::DisposeObject(const InstanceId& uid) const
402 {
403 std::unique_lock lock { disposalMutex_ };
404 disposals_.push_back(uid);
405 ++purgeCounter_;
406 }
407
ConstructMetadata() const408 IMetadata::Ptr ObjectRegistry::ConstructMetadata() const
409 {
410 return IMetadata::Ptr { new Internal::Metadata };
411 }
412
ConstructDefaultCallContext() const413 ICallContext::Ptr ObjectRegistry::ConstructDefaultCallContext() const
414 {
415 return ICallContext::Ptr { new DefaultCallContext };
416 }
417
GetAllObjectInstances() const418 BASE_NS::vector<IObject::Ptr> ObjectRegistry::GetAllObjectInstances() const
419 {
420 CheckGC();
421 BASE_NS::vector<IObject::Ptr> result;
422 std::shared_lock lock { mutex_ };
423 result.reserve(instancesByUid_.size());
424 for (const auto& v : instancesByUid_) {
425 if (auto strong = v.second.ptr.lock()) {
426 result.emplace_back(strong);
427 }
428 }
429 return result;
430 }
431
GetAllSingletonObjectInstances() const432 BASE_NS::vector<IObject::Ptr> ObjectRegistry::GetAllSingletonObjectInstances() const
433 {
434 CheckGC();
435 BASE_NS::vector<IObject::Ptr> result;
436 std::shared_lock lock { mutex_ };
437 if (!singletons_.empty()) {
438 result.reserve(singletons_.size());
439 for (const auto& s : singletons_) {
440 if (auto strong = s.second.lock()) {
441 result.push_back(strong);
442 }
443 }
444 }
445 return result;
446 }
447
GetObjectInstancesByCategory(ObjectCategoryBits category,bool strict) const448 BASE_NS::vector<IObject::Ptr> ObjectRegistry::GetObjectInstancesByCategory(
449 ObjectCategoryBits category, bool strict) const
450 {
451 CheckGC();
452 BASE_NS::vector<IObject::Ptr> result;
453 std::shared_lock lock { mutex_ };
454 for (const auto& i : instancesByUid_) {
455 if (CheckCategoryBits(static_cast<ObjectCategoryBits>(i.second.category), category, strict)) {
456 if (auto strong = i.second.ptr.lock()) {
457 result.emplace_back(strong);
458 }
459 }
460 }
461 return result;
462 }
463
FindSingleton(const BASE_NS::Uid uid) const464 IObject::Ptr ObjectRegistry::FindSingleton(const BASE_NS::Uid uid) const
465 {
466 auto it = singletons_.find(uid);
467 return it != singletons_.end() ? it->second.lock() : nullptr;
468 }
469
GetObjectInstanceByInstanceId(InstanceId uid) const470 IObject::Ptr ObjectRegistry::GetObjectInstanceByInstanceId(InstanceId uid) const
471 {
472 if (uid == BASE_NS::Uid()) {
473 // invalid/zero/empty UID.
474 return nullptr;
475 }
476
477 CheckGC();
478
479 std::shared_lock lock { mutex_ };
480
481 // See if it's an singleton.
482 auto sing = FindSingleton(uid.ToUid());
483 if (sing) {
484 return sing;
485 }
486
487 // Non singletons then
488 auto it2 = instancesByUid_.find(uid);
489 if (it2 != instancesByUid_.end()) {
490 if (auto strong = it2->second.ptr.lock()) {
491 return strong;
492 }
493 }
494
495 // No such instance then
496 return nullptr;
497 }
498
ExportToString(const IObjectRegistryExporter::Ptr & exporter) const499 BASE_NS::string ObjectRegistry::ExportToString(const IObjectRegistryExporter::Ptr& exporter) const
500 {
501 return exporter ? exporter->ExportRegistry(this) : "";
502 }
503
GetDefaultObjectContext() const504 IObjectContext::Ptr ObjectRegistry::GetDefaultObjectContext() const
505 {
506 {
507 std::shared_lock lock { mutex_ };
508 if (defaultContext_) {
509 return defaultContext_;
510 }
511 }
512
513 IObjectContext::Ptr context = interface_pointer_cast<IObjectContext>(
514 Create(ClassId::ObjectContext, { GlobalObjectInstance::DEFAULT_OBJECT_CONTEXT, true }));
515
516 std::unique_lock lock { mutex_ };
517 // still not set?
518 if (!defaultContext_) {
519 defaultContext_ = context;
520 }
521 CORE_ASSERT(defaultContext_);
522 return defaultContext_;
523 }
524
GetTaskQueue(const BASE_NS::Uid & queueId) const525 ITaskQueue::Ptr ObjectRegistry::GetTaskQueue(const BASE_NS::Uid& queueId) const
526 {
527 std::shared_lock lock { mutex_ };
528 if (auto queue = queues_.find(queueId); queue != queues_.end()) {
529 return queue->second;
530 }
531 CORE_LOG_W("Cannot get task queue, task queue not registered: %s", BASE_NS::to_string(queueId).data());
532 return {};
533 }
534
RegisterTaskQueue(const ITaskQueue::Ptr & queue,const BASE_NS::Uid & queueId)535 bool ObjectRegistry::RegisterTaskQueue(const ITaskQueue::Ptr& queue, const BASE_NS::Uid& queueId)
536 {
537 std::unique_lock lock { mutex_ };
538 if (!queue) {
539 if (auto existing = queues_.find(queueId); existing != queues_.end()) {
540 queues_.erase(existing);
541 return true;
542 }
543 // Null queue but no existing queue found
544 return false;
545 }
546 queues_[queueId] = queue;
547 return true;
548 }
549
UnregisterTaskQueue(const BASE_NS::Uid & queueId)550 bool ObjectRegistry::UnregisterTaskQueue(const BASE_NS::Uid& queueId)
551 {
552 std::unique_lock lock { mutex_ };
553 if (auto existing = queues_.find(queueId); existing != queues_.end()) {
554 queues_.erase(existing);
555 return true;
556 }
557 return false;
558 }
559
HasTaskQueue(const BASE_NS::Uid & queueId) const560 bool ObjectRegistry::HasTaskQueue(const BASE_NS::Uid& queueId) const
561 {
562 std::shared_lock lock { mutex_ };
563 return queues_.find(queueId) != queues_.end();
564 }
565
UnregisterAllTaskQueues()566 bool ObjectRegistry::UnregisterAllTaskQueues()
567 {
568 std::unique_lock lock { mutex_ };
569 queues_.clear();
570 return true;
571 }
572
GetCurrentTaskQueueImpl()573 static ITaskQueue::WeakPtr& GetCurrentTaskQueueImpl()
574 {
575 static thread_local ITaskQueue::WeakPtr q;
576 return q;
577 }
578
GetCurrentTaskQueue() const579 ITaskQueue::Ptr ObjectRegistry::GetCurrentTaskQueue() const
580 {
581 return GetCurrentTaskQueueImpl().lock();
582 }
SetCurrentTaskQueue(ITaskQueue::WeakPtr q)583 ITaskQueue::WeakPtr ObjectRegistry::SetCurrentTaskQueue(ITaskQueue::WeakPtr q)
584 {
585 auto& impl = GetCurrentTaskQueueImpl();
586 auto res = impl;
587 impl = q;
588 return res;
589 }
590
RegisterInterpolator(TypeId propertyTypeUid,BASE_NS::Uid interpolatorClassUid)591 void ObjectRegistry::RegisterInterpolator(TypeId propertyTypeUid, BASE_NS::Uid interpolatorClassUid)
592 {
593 std::unique_lock lock { mutex_ };
594 interpolatorConstructors_[propertyTypeUid] = interpolatorClassUid;
595 }
596
UnregisterInterpolator(TypeId propertyTypeUid)597 void ObjectRegistry::UnregisterInterpolator(TypeId propertyTypeUid)
598 {
599 std::unique_lock lock { mutex_ };
600 interpolatorConstructors_.erase(propertyTypeUid);
601 }
602
HasInterpolator(TypeId propertyTypeUid) const603 bool ObjectRegistry::HasInterpolator(TypeId propertyTypeUid) const
604 {
605 std::shared_lock lock { mutex_ };
606 return interpolatorConstructors_.contains(propertyTypeUid);
607 }
608
CreateInterpolator(TypeId propertyTypeUid)609 IInterpolator::Ptr ObjectRegistry::CreateInterpolator(TypeId propertyTypeUid)
610 {
611 TypeId uid;
612 {
613 std::shared_lock lock { mutex_ };
614 if (auto it = interpolatorConstructors_.find(propertyTypeUid); it != interpolatorConstructors_.end()) {
615 uid = it->second;
616 }
617 }
618 if (uid != TypeId {}) {
619 return interface_pointer_cast<IInterpolator>(Create(uid.ToUid(), CreateInfo {}));
620 }
621 // We don't have an interpolator for the given property type, return the default interpolator (which just steps the
622 // value)
623 CORE_LOG_D("No interpolator for property type %s, falling back to default interpolator",
624 propertyTypeUid.ToString().c_str());
625 return interface_pointer_cast<IInterpolator>(IObjectRegistry::Create(ClassId::DefaultInterpolator));
626 }
627
GetInterface(const BASE_NS::Uid & uid) const628 const CORE_NS::IInterface* ObjectRegistry::GetInterface(const BASE_NS::Uid& uid) const
629 {
630 const CORE_NS::IInterface* result = nullptr;
631 if (uid == CORE_NS::IInterface::UID) {
632 const IObjectRegistry* obj = static_cast<const IObjectRegistry*>(this);
633 result = static_cast<const IInterface*>(obj);
634 }
635 if (uid == IObjectRegistry::UID) {
636 result = static_cast<const IObjectRegistry*>(this);
637 }
638 if (uid == ITaskQueueRegistry::UID) {
639 result = static_cast<const ITaskQueueRegistry*>(this);
640 }
641 return result;
642 }
GetInterface(const BASE_NS::Uid & uid)643 CORE_NS::IInterface* ObjectRegistry::GetInterface(const BASE_NS::Uid& uid)
644 {
645 CORE_NS::IInterface* result = nullptr;
646 if (uid == CORE_NS::IInterface::UID) {
647 IObjectRegistry* obj = static_cast<IObjectRegistry*>(this);
648 result = static_cast<IInterface*>(obj);
649 }
650 if (uid == IObjectRegistry::UID) {
651 result = static_cast<IObjectRegistry*>(this);
652 }
653 if (uid == ITaskQueueRegistry::UID) {
654 result = static_cast<ITaskQueueRegistry*>(this);
655 }
656 return result;
657 }
Ref()658 void ObjectRegistry::Ref() {}
Unref()659 void ObjectRegistry::Unref() {}
660
GetPropertyRegister()661 META_NS::IPropertyRegister& ObjectRegistry::GetPropertyRegister()
662 {
663 return *this;
664 }
665
Create(const ObjectId & object,BASE_NS::string_view name) const666 META_NS::IProperty::Ptr ObjectRegistry::Create(const ObjectId& object, BASE_NS::string_view name) const
667 {
668 if (object == ClassId::StackProperty) {
669 auto p = META_NS::IProperty::Ptr(new META_NS::Internal::StackProperty(BASE_NS::string(name)));
670 if (auto i = interface_cast<IPropertyInternal>(p)) {
671 i->SetSelf(p);
672 }
673 return p;
674 }
675 return nullptr;
676 }
CreateBind() const677 IBind::Ptr ObjectRegistry::CreateBind() const
678 {
679 return interface_pointer_cast<IBind>(Create(ClassId::Bind, CreateInfo {}));
680 }
InvalidAny() const681 IAny& ObjectRegistry::InvalidAny() const
682 {
683 static DummyAny any;
684 return any;
685 }
ConstructAny(const ObjectId & id) const686 IAny::Ptr ObjectRegistry::ConstructAny(const ObjectId& id) const
687 {
688 std::shared_lock lock { mutex_ };
689 auto it = anyBuilders_.find(id);
690 return it != anyBuilders_.end() ? it->second->Construct() : nullptr;
691 }
IsAnyRegistered(const ObjectId & id) const692 bool ObjectRegistry::IsAnyRegistered(const ObjectId& id) const
693 {
694 std::shared_lock lock { mutex_ };
695 return anyBuilders_.find(id) != anyBuilders_.end();
696 }
RegisterAny(BASE_NS::shared_ptr<AnyBuilder> builder)697 void ObjectRegistry::RegisterAny(BASE_NS::shared_ptr<AnyBuilder> builder)
698 {
699 std::unique_lock lock { mutex_ };
700 if (anyBuilders_.find(builder->GetObjectId()) != anyBuilders_.end()) {
701 CORE_LOG_W("Any already registered [id=%s]", builder->GetObjectId().ToString().c_str());
702 }
703 anyBuilders_[builder->GetObjectId()] = builder;
704 }
UnregisterAny(const ObjectId & id)705 void ObjectRegistry::UnregisterAny(const ObjectId& id)
706 {
707 std::unique_lock lock { mutex_ };
708 anyBuilders_.erase(id);
709 }
GetGlobalSerializationData()710 IGlobalSerializationData& ObjectRegistry::GetGlobalSerializationData()
711 {
712 return *this;
713 }
GetDefaultSettings() const714 SerializationSettings ObjectRegistry::GetDefaultSettings() const
715 {
716 std::shared_lock lock { mutex_ };
717 return defaultSettings_;
718 }
SetDefaultSettings(const SerializationSettings & settings)719 void ObjectRegistry::SetDefaultSettings(const SerializationSettings& settings)
720 {
721 std::unique_lock lock { mutex_ };
722 defaultSettings_ = settings;
723 }
RegisterGlobalObject(const IObject::Ptr & object)724 void ObjectRegistry::RegisterGlobalObject(const IObject::Ptr& object)
725 {
726 std::unique_lock lock { mutex_ };
727 if (auto p = interface_cast<IObjectInstance>(object)) {
728 globalObjects_[p->GetInstanceId()] = object;
729 }
730 }
UnregisterGlobalObject(const IObject::Ptr & object)731 void ObjectRegistry::UnregisterGlobalObject(const IObject::Ptr& object)
732 {
733 std::unique_lock lock { mutex_ };
734 if (auto p = interface_cast<IObjectInstance>(object)) {
735 globalObjects_.erase(p->GetInstanceId());
736 }
737 }
GetGlobalObject(const InstanceId & id) const738 IObject::Ptr ObjectRegistry::GetGlobalObject(const InstanceId& id) const
739 {
740 std::shared_lock lock { mutex_ };
741 auto it = globalObjects_.find(id);
742 return it != globalObjects_.end() ? it->second.lock() : nullptr;
743 }
RegisterValueSerializer(const IValueSerializer::Ptr & s)744 void ObjectRegistry::RegisterValueSerializer(const IValueSerializer::Ptr& s)
745 {
746 std::unique_lock lock { mutex_ };
747 valueSerializers_[s->GetTypeId()] = s;
748 }
UnregisterValueSerializer(const TypeId & id)749 void ObjectRegistry::UnregisterValueSerializer(const TypeId& id)
750 {
751 std::unique_lock lock { mutex_ };
752 valueSerializers_.erase(id);
753 }
GetValueSerializer(const TypeId & id) const754 IValueSerializer::Ptr ObjectRegistry::GetValueSerializer(const TypeId& id) const
755 {
756 std::shared_lock lock { mutex_ };
757 auto it = valueSerializers_.find(id);
758 return it != valueSerializers_.end() ? it->second : nullptr;
759 }
760
GetInternalValueAccess(const CORE_NS::PropertyTypeDecl & type) const761 IEngineInternalValueAccess::Ptr ObjectRegistry::GetInternalValueAccess(const CORE_NS::PropertyTypeDecl& type) const
762 {
763 std::shared_lock lock { mutex_ };
764 auto it = engineInternalAccess_.find(type);
765 return it != engineInternalAccess_.end() ? it->second : nullptr;
766 }
RegisterInternalValueAccess(const CORE_NS::PropertyTypeDecl & type,IEngineInternalValueAccess::Ptr ptr)767 void ObjectRegistry::RegisterInternalValueAccess(
768 const CORE_NS::PropertyTypeDecl& type, IEngineInternalValueAccess::Ptr ptr)
769 {
770 std::unique_lock lock { mutex_ };
771 engineInternalAccess_[type] = BASE_NS::move(ptr);
772 }
UnregisterInternalValueAccess(const CORE_NS::PropertyTypeDecl & type)773 void ObjectRegistry::UnregisterInternalValueAccess(const CORE_NS::PropertyTypeDecl& type)
774 {
775 std::unique_lock lock { mutex_ };
776 engineInternalAccess_.erase(type);
777 }
GetEngineData()778 IEngineData& ObjectRegistry::GetEngineData()
779 {
780 return *this;
781 }
782 META_END_NAMESPACE()
783