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