• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_V("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_MSG(defaultContext_, "Failed to create default object context");
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_V("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