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#ifndef META_SRC_PROPERTY_H
16#define META_SRC_PROPERTY_H
17
18#include <atomic>
19#include <memory>
20#include <mutex>
21
22#include <meta/base/namespace.h>
23#include <meta/base/types.h>
24#include <meta/ext/event_impl.h>
25#include <meta/ext/minimal_object.h>
26#include <meta/interface/intf_any.h>
27#include <meta/interface/intf_lockable.h>
28#include <meta/interface/property/intf_modifier.h>
29#include <meta/interface/property/intf_property_internal.h>
30#include <meta/interface/property/property_events.h>
31
32META_BEGIN_NAMESPACE()
33namespace Internal {
34
35META_REGISTER_CLASS(Property, "1801d9a9-3557-4e0d-b90e-54791acd6768", ObjectCategoryBits::NO_CATEGORY)
36
37class PropertyBase : public MinimalObject<ClassId::Property, IProperty, IPropertyInternal, ILockable, IValue> {
38public:
39    using OnChangedEvent = EventImpl<IOnChanged>;
40
41    PropertyBase(BASE_NS::string name) : name_(BASE_NS::move(name)) {}
42
43    BASE_NS::string GetName() const override;
44
45    IObject::WeakPtr GetOwner() const override;
46    void SetOwner(IObject::Ptr owner) override;
47    void SetSelf(IProperty::Ptr self) override;
48
49    AnyReturnValue SetValue(const IAny& value) override;
50    const IAny& GetValue() const override;
51    bool IsCompatible(const TypeId& id) const override;
52
53    TypeId GetTypeId() const override;
54    void NotifyChange() const override;
55
56    IEvent::Ptr EventOnChanged() const override;
57
58    void Lock() const override;
59    void Unlock() const override;
60    void LockShared() const override;
61    void UnlockShared() const override;
62
63protected:
64    virtual IAny::Ptr& GetData() const = 0;
65    AnyReturnValue SetInternalValue(const IAny& value);
66    void CallOnChanged() const;
67
68protected:
69    // this has to be recursive because of the usage pattern
70    mutable std::recursive_mutex mutex_;
71    mutable size_t locked_ {};
72    mutable bool pendingInvoke_ {};
73    const BASE_NS::string name_;
74    IObject::WeakPtr owner_;
75    IProperty::WeakPtr self_;
76    // lazy event, constructed when needed
77    mutable BASE_NS::shared_ptr<OnChangedEvent> onChanged_;
78    mutable std::atomic<OnChangedEvent*> onChangedAtomic_ {};
79};
80
81class GenericProperty : public IntroduceInterfaces<PropertyBase, IPropertyInternalAny> {
82    using Super = IntroduceInterfaces<PropertyBase, IPropertyInternalAny>;
83
84public:
85    using Super::Super;
86
87    AnyReturnValue SetInternalAny(IAny::Ptr any) override;
88    IAny::Ptr GetInternalAny() const override;
89
90protected:
91    IAny::Ptr& GetData() const override
92    {
93        return data_;
94    }
95
96private:
97    mutable IAny::Ptr data_;
98};
99
100} // namespace Internal
101META_END_NAMESPACE()
102
103#endif