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