123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- #pragma once
- #include "actor.hpp"
- #include "message.hpp"
- #include "planner.hpp"
- #include "queue.hpp"
- #include "rotor-light-bsp.h"
- #include <tuple>
- #include <type_traits>
- #include <utility>
- namespace rotor_light {
- namespace details {
- struct ChildState {
-
- State down_state = State::off;
- };
- }
- struct SupervisorBase : ActorBase {
- friend struct ActorBase;
-
- static constexpr size_t min_handlers_amount =
- ActorBase::min_handlers_amount + 2;
-
- using Parent = ActorBase;
-
- SupervisorBase(char *backends, size_t backends_count, ActorBase **actors,
- details::ChildState *states, size_t actors_count);
-
- inline QueueBase *get_queue() { return queue; }
- void initialize() override;
-
- void start(bool poll_timer = false);
-
- virtual void bind(Context &context, ActorId value = 0);
- uint8_t bind(ActorId initial_value, SupervisorBase *supervisor,
- Context &context) override;
-
- void process();
-
- void advance_init() override;
- void advance_start() override;
- void advance_stop() override;
-
- inline PlannerBase *get_planner() { return planner; }
- protected:
-
- virtual void on_refhesh_timer(message::RefreshTime &);
-
- ActorBase **actors;
-
- details::ChildState *states;
-
- size_t actors_count;
-
- QueueBase *queue;
-
- PlannerBase *planner;
-
- NowFunction now;
- private:
- void on_state_change_ack(message::ChangeStateAck &);
- void on_child_init_failure(size_t actor_index);
- void dispatch(Message &);
- void on_child_down(size_t actor_index);
- void init_child(size_t actor_index);
- void start_actor(size_t actor_index);
- size_t process_watchdog();
- bool check_child_state(State subject, bool skip_self);
- };
- template <size_t HandlersCount, typename... Actors>
- struct Supervisor : SupervisorBase {
- static_assert(HandlersCount >= SupervisorBase::min_handlers_amount,
- "no enough handlers");
- Supervisor()
- : SupervisorBase(reinterpret_cast<char *>(&backends), HandlersCount,
- actors, children_states_holder, children_count + 1) {
- actors[0] = this;
- fill_actor<0>();
- }
-
- template <size_t ChildIndex> auto get_child() {
- return &std::get<ChildIndex>(children);
- }
- protected:
-
- using ActorsList = std::tuple<Actors...>;
-
- static constexpr size_t children_count = std::tuple_size_v<ActorsList>;
-
- ActorsList children;
-
- ActorBase::Handler backends[HandlersCount];
-
- ActorBase *actors[children_count + 1];
-
- details::ChildState children_states_holder[children_count + 1];
- private:
- template <size_t ChildIndex> void fill_actor() {
- if constexpr (ChildIndex < children_count) {
- actors[ChildIndex + 1] = get_child<ChildIndex>();
- fill_actor<ChildIndex + 1>();
- }
- }
- };
- template <typename Ctx, typename MessageType, bool force, typename... Args>
- bool ActorBase::send_impl(size_t queue_index, Args &&...args) {
- auto &queue = supervisor->queue;
- if constexpr (std::is_same_v<Ctx, ctx::thread>) {
- ROTOR_LIGHT_DISABLE_INTERRUPTS();
- }
- auto result =
- queue->put<MessageType, force>(queue_index, std::forward<Args>(args)...);
- if constexpr (std::is_same_v<Ctx, ctx::thread>) {
- ROTOR_LIGHT_ENABLE_INTERRUPTS();
- }
- return result;
- }
- template <typename Ctx>
- EventId ActorBase::add_event(Duration delta, Callback callback, void *data) {
- assert(supervisor->now && supervisor->planner);
- if constexpr (std::is_same_v<Ctx, ctx::thread>) {
- ROTOR_LIGHT_DISABLE_INTERRUPTS();
- }
- auto when = supervisor->now() + delta;
- auto p = supervisor->planner;
- auto result = p->add_event<ctx::interrupt>(when, callback, data);
- if constexpr (std::is_same_v<Ctx, ctx::thread>) {
- ROTOR_LIGHT_ENABLE_INTERRUPTS();
- }
- return result;
- }
- }
|