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#ifndef META_SRC_OBJECT_REGISTRY_H
17#define META_SRC_OBJECT_REGISTRY_H
18
19#include <atomic>
20#include <shared_mutex>
21
22#include <base/containers/unordered_map.h>
23
24#include <meta/base/interface_macros.h>
25#include <meta/base/namespace.h>
26#include <meta/interface/animation/intf_interpolator.h>
27#include <meta/interface/engine/intf_engine_data.h>
28#include <meta/interface/intf_call_context.h>
29#include <meta/interface/intf_metadata.h>
30#include <meta/interface/intf_object_context.h>
31#include <meta/interface/intf_object_registry.h>
32#include <meta/interface/intf_task_queue_registry.h>
33
34#include "class_registry.h"
35
36META_BEGIN_NAMESPACE()
37
38class IRandom {
39public:
40    virtual ~IRandom() = default;
41    virtual void Initialize(uint64_t seed) = 0;
42    virtual uint64_t GetRandom() = 0;
43};
44
45class ObjectRegistry final : public IObjectRegistry,
46                             public ITaskQueueRegistry,
47                             public IPropertyRegister,
48                             public IGlobalSerializationData,
49                             public IEngineData {
50public:
51    META_NO_COPY_MOVE(ObjectRegistry)
52
53    ObjectRegistry();
54    ~ObjectRegistry() override;
55
56    IClassRegistry& GetClassRegistry() override;
57
58    bool RegisterObjectType(const IClassInfo::Ptr& classInfo) override;
59    bool UnregisterObjectType(const IClassInfo::Ptr& classInfo) override;
60
61    IObject::Ptr Create(ObjectId uid, const CreateInfo& createInfo, const IMetadata::Ptr& data) const override;
62    IObject::Ptr Create(ObjectId uid, const CreateInfo& createInfo) const override;
63    IObject::Ptr Create(const ClassInfo& info, const CreateInfo& createInfo) const override;
64
65    IObjectFactory::ConstPtr GetObjectFactory(const ObjectId& uid) const override;
66    BASE_NS::vector<ObjectCategoryItem> GetAllCategories() const override;
67    BASE_NS::vector<IClassInfo::ConstPtr> GetAllTypes(
68        ObjectCategoryBits category, bool strict, bool excludeDeprecated) const override;
69
70    IObject::Ptr GetObjectInstanceByInstanceId(InstanceId uid) const override;
71    BASE_NS::vector<IObject::Ptr> GetAllObjectInstances() const override;
72    BASE_NS::vector<IObject::Ptr> GetAllSingletonObjectInstances() const override;
73    BASE_NS::vector<IObject::Ptr> GetObjectInstancesByCategory(ObjectCategoryBits category, bool strict) const override;
74
75    BASE_NS::string ExportToString(const IObjectRegistryExporter::Ptr& exporter) const override;
76    IObjectContext::Ptr GetDefaultObjectContext() const override;
77
78    void Purge() override;
79    void DisposeObject(const InstanceId&) const override;
80    IMetadata::Ptr ConstructMetadata() const override;
81    ICallContext::Ptr ConstructDefaultCallContext() const override;
82
83    const IInterface* GetInterface(const BASE_NS::Uid& uid) const override;
84    IInterface* GetInterface(const BASE_NS::Uid& uid) override;
85
86    IPropertyRegister& GetPropertyRegister() override;
87    IProperty::Ptr Create(const ObjectId& object, BASE_NS::string_view name) const override;
88    IBind::Ptr CreateBind() const override;
89    IAny& InvalidAny() const override;
90    IAny::Ptr ConstructAny(const ObjectId& id) const override;
91    bool IsAnyRegistered(const ObjectId& id) const override;
92    void RegisterAny(BASE_NS::shared_ptr<AnyBuilder> builder) override;
93    void UnregisterAny(const ObjectId& id) override;
94
95    // Interpolators
96    void RegisterInterpolator(TypeId propertyTypeUid, BASE_NS::Uid interpolatorClassUid) override;
97    void UnregisterInterpolator(TypeId propertyTypeUid) override;
98    bool HasInterpolator(TypeId propertyTypeUid) const override;
99    IInterpolator::Ptr CreateInterpolator(TypeId propertyTypeUid) override;
100
101    IGlobalSerializationData& GetGlobalSerializationData() override;
102    SerializationSettings GetDefaultSettings() const override;
103    void SetDefaultSettings(const SerializationSettings& settings) override;
104    void RegisterGlobalObject(const IObject::Ptr& object) override;
105    void UnregisterGlobalObject(const IObject::Ptr& object) override;
106    IObject::Ptr GetGlobalObject(const InstanceId& id) const override;
107    void RegisterValueSerializer(const IValueSerializer::Ptr&) override;
108    void UnregisterValueSerializer(const TypeId& id) override;
109    IValueSerializer::Ptr GetValueSerializer(const TypeId& id) const override;
110
111    IEngineInternalValueAccess::Ptr GetInternalValueAccess(const CORE_NS::PropertyTypeDecl& type) const override;
112    void RegisterInternalValueAccess(const CORE_NS::PropertyTypeDecl& type, IEngineInternalValueAccess::Ptr) override;
113    void UnregisterInternalValueAccess(const CORE_NS::PropertyTypeDecl& type) override;
114    IEngineData& GetEngineData() override;
115
116protected:
117    void Ref() override;
118    void Unref() override;
119
120protected: // ITaskQueueRegistry
121    ITaskQueue::Ptr GetTaskQueue(const BASE_NS::Uid& queueId) const override;
122    bool RegisterTaskQueue(const ITaskQueue::Ptr& queue, const BASE_NS::Uid& queueId) override;
123    bool UnregisterTaskQueue(const BASE_NS::Uid& queueId) override;
124    bool HasTaskQueue(const BASE_NS::Uid& queueId) const override;
125    bool UnregisterAllTaskQueues() override;
126    ITaskQueue::Ptr GetCurrentTaskQueue() const override;
127    ITaskQueue::WeakPtr SetCurrentTaskQueue(ITaskQueue::WeakPtr) override;
128
129private:
130    struct CreateResult {
131        bool successful;
132        uint64_t category;
133        bool singleton = false;
134    };
135
136    CreateResult CreateInternal(BASE_NS::Uid uid, BASE_NS::vector<IObject::Ptr>& classes) const;
137    bool ConstructObjectInternal(const IObject::Ptr& obj, BASE_NS::vector<IObject::Ptr>& classes) const;
138    void SetObjectInstanceIds(const BASE_NS::vector<IObject::Ptr>& classes, InstanceId instid) const;
139    bool BuildObject(const BASE_NS::vector<IObject::Ptr>& classes, const IMetadata::Ptr& data) const;
140    bool PostCreate(const BASE_NS::Uid& uid, InstanceId instid, const CreateResult& t, const CreateInfo& createInfo,
141        const BASE_NS::vector<IObject::Ptr>& classes, const IMetadata::Ptr& data) const;
142
143    BASE_NS::string GetClassName(BASE_NS::Uid uid) const;
144    IObject::Ptr FindSingleton(const BASE_NS::Uid uid) const;
145    void CheckGC() const;
146    void GC() const;
147    void DoDisposal(const BASE_NS::vector<InstanceId>& uids) const;
148
149    struct ObjectInstance {
150        IObject::WeakPtr ptr;
151        uint64_t category {};
152    };
153
154    mutable std::shared_mutex mutex_;
155    mutable std::shared_mutex disposalMutex_;
156
157    BASE_NS::unique_ptr<IRandom> random_;
158
159    // mutable so GC can clean up null objects. (GC is called from const methods)
160    mutable BASE_NS::unordered_map<InstanceId, IObject::WeakPtr> singletons_;
161    mutable BASE_NS::unordered_map<InstanceId, ObjectInstance> instancesByUid_;
162    mutable IObjectContext::Ptr defaultContext_;
163
164    mutable std::atomic_flag disposalInProgress_ = ATOMIC_FLAG_INIT;
165    mutable std::atomic<size_t> purgeCounter_ {};
166    mutable BASE_NS::vector<InstanceId> disposals_;
167    mutable BASE_NS::vector<InstanceId> disposalsStorage_;
168
169    BASE_NS::unordered_map<BASE_NS::Uid, ITaskQueue::Ptr> queues_;
170
171    ClassRegistry classRegistry_;
172
173    // Interpolator constructors.
174    BASE_NS::unordered_map<TypeId, BASE_NS::Uid> interpolatorConstructors_;
175
176    SerializationSettings defaultSettings_;
177    mutable BASE_NS::unordered_map<InstanceId, IObject::WeakPtr> globalObjects_;
178    BASE_NS::unordered_map<TypeId, IValueSerializer::Ptr> valueSerializers_;
179
180    BASE_NS::unordered_map<ObjectId, BASE_NS::shared_ptr<AnyBuilder>> anyBuilders_;
181    BASE_NS::unordered_map<CORE_NS::PropertyTypeDecl, IEngineInternalValueAccess::Ptr> engineInternalAccess_;
182};
183
184META_END_NAMESPACE()
185
186#endif
187