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_STARTABLE_OBJECT_CONTROLLER_H
17 #define META_SRC_STARTABLE_OBJECT_CONTROLLER_H
18 
19 #include <shared_mutex>
20 
21 #include <base/containers/unordered_map.h>
22 
23 #include <meta/api/timer.h>
24 #include <meta/ext/attachment/attachment.h>
25 #include <meta/interface/builtin_objects.h>
26 #include <meta/interface/intf_object_hierarchy_observer.h>
27 #include <meta/interface/intf_startable_controller.h>
28 #include <meta/interface/intf_task_queue.h>
29 #include <meta/interface/intf_tickable_controller.h>
30 
META_BEGIN_NAMESPACE()31 META_BEGIN_NAMESPACE()
32 
33 class IStartableObjectControllerInternal : public CORE_NS::IInterface {
34     META_INTERFACE(CORE_NS::IInterface, IStartableObjectControllerInternal, "fd5c13af-de72-4cc4-bed0-07cb6a751ac1")
35 public:
36     /**
37      * @brief Run tasks with given queueId.
38      */
39     virtual void RunTasks(const BASE_NS::Uid& queueId) = 0;
40 };
41 
42 class StartableObjectController
43     : public META_NS::MetaObjectFwd<StartableObjectController, ClassId::StartableObjectController, ClassId::MetaObject,
44           IStartableController, IObjectHierarchyObserver, IStartableObjectControllerInternal, ITickableController> {
45 public: // ILifeCycle
46     bool Build(const IMetadata::Ptr& data) override;
47     void Destroy() override;
48 
49 public: // IStartableController
50     META_IMPLEMENT_INTERFACE_PROPERTY(
51         IStartableController, META_NS::TraversalType, TraversalType, META_NS::TraversalType::DEPTH_FIRST_POST_ORDER)
52     META_IMPLEMENT_INTERFACE_PROPERTY(
53         IStartableController, META_NS::StartBehavior, StartBehavior, META_NS::StartBehavior::AUTOMATIC)
54     bool StartAll(ControlBehavior behavior) override;
55     bool StopAll(ControlBehavior behavior) override;
56     BASE_NS::vector<IStartable::Ptr> GetAllStartables() const override;
57     bool SetStartableQueueId(
58         const BASE_NS::Uid& startStartableQueueId, const BASE_NS::Uid& stopStartableQueueId) override;
59 
60 public: // IObjectHierarchyObserver
61     void SetTarget(const IObject::Ptr& root, HierarchyChangeModeValue mode) override;
62     IObject::Ptr GetTarget() const override;
63     BASE_NS::vector<IObject::Ptr> GetAllObserved() const override;
64     META_FORWARD_EVENT(IOnHierarchyChanged, OnHierarchyChanged, observer_->EventOnHierarchyChanged())
65 
66 public: // ITickableController
67     BASE_NS::vector<ITickable::Ptr> GetTickables() const override;
68     void TickAll(const TimeSpan& time) override;
69     META_IMPLEMENT_INTERFACE_PROPERTY(
70         ITickableController, META_NS::TimeSpan, TickInterval, META_NS::TimeSpan::Infinite())
71     META_IMPLEMENT_INTERFACE_PROPERTY(
72         ITickableController, META_NS::TraversalType, TickOrder, META_NS::TraversalType::DEPTH_FIRST_PRE_ORDER)
73     bool SetTickableQueueuId(const BASE_NS::Uid& queueId) override;
74 
75 private:
76     void StartHierarchy(const IObject::Ptr& root, ControlBehavior behavior);
77     void StopHierarchy(const IObject::Ptr& root, ControlBehavior behavior);
78     void StartStartable(IStartable* const startable, ControlBehavior behavior);
79     void StopStartable(IStartable* const startable, ControlBehavior behavior);
80     void HierarchyChanged(const HierarchyChangedInfo& info);
81 
82     IObject::WeakPtr target_;
83     IObjectHierarchyObserver::Ptr observer_;
84 
85 private: // IStartableObjectControllerInternal
86     void RunTasks(const BASE_NS::Uid& queueId) override;
87 
88 private: // Task queue handling
89     struct StartableOperation {
90         enum Operation {
91             /** Run StartHierarchy() for root_ */
92             START,
93             /** Run StopHierarchy() for root_ */
94             STOP,
95         };
96 
97         Operation operation_;
98         IObject::WeakPtr root_;
99     };
100 
101     BASE_NS::Uid startQueueId_;
102     BASE_NS::Uid stopQueueId_;
103     bool HasTasks(const BASE_NS::Uid& queueId) const;
104     bool ProcessOps(const BASE_NS::Uid& queueId);
105     bool AddOperation(StartableOperation&& operation, const BASE_NS::Uid& queue);
106     BASE_NS::unordered_map<BASE_NS::Uid, BASE_NS::vector<StartableOperation>> operations_;
107     mutable std::shared_mutex mutex_;
108     std::size_t executingStart_ {};
109 
110 private: // Tickables
111     void InvalidateTickables();
112     void UpdateTicker();
113     mutable BASE_NS::vector<ITickable::WeakPtr> tickables_;
114     mutable std::shared_mutex tickMutex_;
115     mutable bool tickablesValid_ { false };
116     TimeSpan lastTick_ { TimeSpan::Infinite() };
117     IClock::Ptr clock_;
118     BASE_NS::Uid tickQueueId_;
119     ITaskQueue::Ptr tickerQueue_;
120     ITaskQueue::Ptr defaultTickerQueue_;
121     ITaskQueueTask::Ptr tickerTask_;
122     ITaskQueue::Token tickerToken_ {};
123 };
124 
125 META_END_NAMESPACE()
126 
127 #endif // META_SRC_STARTABLE_OBJECT_CONTROLLER_H
128