* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef META_SRC_STARTABLE_OBJECT_CONTROLLER_H
#define META_SRC_STARTABLE_OBJECT_CONTROLLER_H
#include <mutex>
#include <shared_mutex>
#include <base/containers/unordered_map.h>
#include <meta/api/timer.h>
#include <meta/base/namespace.h>
#include <meta/ext/attachment/attachment.h>
#include <meta/ext/implementation_macros.h>
#include <meta/interface/builtin_objects.h>
#include <meta/interface/intf_object_hierarchy_observer.h>
#include <meta/interface/intf_startable_controller.h>
#include <meta/interface/intf_task_queue.h>
#include <meta/interface/intf_tickable_controller.h>
META_BEGIN_NAMESPACE()
class IStartableObjectControllerInternal : public CORE_NS::IInterface {
META_INTERFACE(CORE_NS::IInterface, IStartableObjectControllerInternal, "fd5c13af-de72-4cc4-bed0-07cb6a751ac1")
public:
* @brief Run tasks with given queueId.
*/
virtual void RunTasks(const ITaskQueue::Ptr& queue) = 0;
};
class StartableObjectController : public IntroduceInterfaces<ObjectFwd, IStartableController, IObjectHierarchyObserver,
IStartableObjectControllerInternal, ITickableController> {
META_OBJECT(StartableObjectController, ClassId::StartableObjectController, IntroduceInterfaces)
public:
bool Build(const IMetadata::Ptr& data) override;
void Destroy() override;
META_BEGIN_STATIC_DATA()
META_STATIC_PROPERTY_DATA(
IStartableController, META_NS::TraversalType, TraversalType, META_NS::TraversalType::DEPTH_FIRST_POST_ORDER)
META_STATIC_PROPERTY_DATA(
IStartableController, META_NS::StartBehavior, StartBehavior, META_NS::StartBehavior::AUTOMATIC)
META_STATIC_PROPERTY_DATA(ITickableController, META_NS::TimeSpan, TickInterval, META_NS::TimeSpan::Infinite())
META_STATIC_PROPERTY_DATA(
ITickableController, META_NS::TraversalType, TickOrder, META_NS::TraversalType::DEPTH_FIRST_PRE_ORDER)
META_END_STATIC_DATA()
META_IMPLEMENT_PROPERTY(META_NS::TraversalType, TraversalType)
META_IMPLEMENT_PROPERTY(META_NS::StartBehavior, StartBehavior)
META_IMPLEMENT_PROPERTY(META_NS::TimeSpan, TickInterval)
META_IMPLEMENT_PROPERTY(META_NS::TraversalType, TickOrder)
public:
bool StartAll(ControlBehavior behavior) override;
bool StopAll(ControlBehavior behavior) override;
BASE_NS::vector<IStartable::Ptr> GetAllStartables() const override;
bool SetStartableQueueId(
const BASE_NS::Uid& startStartableQueueId, const BASE_NS::Uid& stopStartableQueueId) override;
bool SetStartableQueue(const META_NS::ITaskQueue::Ptr& startStartableQueue,
const META_NS::ITaskQueue::Ptr& stopStartableQueue) override;
public:
void SetTarget(const IObject::Ptr& root, HierarchyChangeModeValue mode) override;
IObject::Ptr GetTarget() const override;
BASE_NS::vector<IObject::Ptr> GetAllObserved() const override;
META_FORWARD_EVENT(IOnHierarchyChanged, OnHierarchyChanged, observer_->EventOnHierarchyChanged)
public:
BASE_NS::vector<ITickable::Ptr> GetTickables() const override;
void TickAll(const TimeSpan& time) override;
bool SetTickableQueueuId(const BASE_NS::Uid& queueId) override;
private:
void StartHierarchy(const IObject::Ptr& root, ControlBehavior behavior);
void StopHierarchy(const IObject::Ptr& root, ControlBehavior behavior);
void StartStartable(IStartable* const startable, ControlBehavior behavior);
void StopStartable(IStartable* const startable, ControlBehavior behavior);
void HierarchyChanged(const HierarchyChangedInfo& info);
IObject::WeakPtr target_;
IObjectHierarchyObserver::Ptr observer_;
private:
void RunTasks(const ITaskQueue::Ptr& queue) override;
private:
struct StartableOperation {
enum Operation {
START,
STOP,
};
Operation operation_;
IObject::WeakPtr root_;
};
mutable META_NS::ITaskQueue::WeakPtr startQueue_;
mutable META_NS::ITaskQueue::WeakPtr stopQueue_;
BASE_NS::Uid startQueueId_;
BASE_NS::Uid stopQueueId_;
bool HasTasks(const ITaskQueue::Ptr& queue) const;
bool ProcessOps(const ITaskQueue::Ptr& queue);
bool AddOperation(StartableOperation&& operation, const ITaskQueue::Ptr& queue);
BASE_NS::unordered_map<ITaskQueue*, BASE_NS::vector<StartableOperation>> operations_;
mutable std::shared_mutex mutex_;
std::size_t executingStart_{};
META_NS::ITaskQueue::Ptr GetStartQueue() const;
META_NS::ITaskQueue::Ptr GetStopQueue() const;
private:
void InvalidateTickables();
void UpdateTicker();
mutable BASE_NS::vector<ITickable::WeakPtr> tickables_;
mutable std::shared_mutex tickMutex_;
mutable bool tickablesValid_{false};
TimeSpan lastTick_{TimeSpan::Infinite()};
IClock::Ptr clock_;
BASE_NS::Uid tickQueueId_;
ITaskQueue::Ptr tickerQueue_;
ITaskQueue::Ptr defaultTickerQueue_;
ITaskQueueTask::Ptr tickerTask_;
ITaskQueue::Token tickerToken_{};
};
META_END_NAMESPACE()
#endif