rotor_light
real-time C++ actor micro-framework for embedded systems, supervisable
supervisor.hpp
1// SPDX-License-Identifier: MIT
2// SPDX-FileCopyrightText: 2022 Ivan Baidakou
3
4#pragma once
5
6#include "actor.hpp"
7#include "message.hpp"
8#include "planner.hpp"
9#include "queue.hpp"
10#include "rotor-light-bsp.h"
11#include <tuple>
12#include <type_traits>
13#include <utility>
14
15namespace rotor_light {
16
17namespace details {
18
21struct ChildState {
23 State down_state = State::off;
24};
25} // namespace details
26
30 friend struct ActorBase;
31
34 static constexpr size_t min_handlers_amount =
36
39
41 SupervisorBase(char *backends, size_t backends_count, ActorBase **actors,
43
45 inline QueueBase *get_queue() { return queue; }
46
47 void initialize() override;
48
55 void start(bool poll_timer = false);
56
65 virtual void bind(Context &context, ActorId value = 0);
66
67 uint8_t bind(ActorId initial_value, SupervisorBase *supervisor,
68 Context &context) override;
69
70
93 void process();
94
95 // handlers
96 void advance_init() override;
97 void advance_start() override;
98 void advance_stop() override;
99
101 inline PlannerBase *get_planner() { return planner; }
102
103protected:
112
115
118
121
124
127
129 NowFunction now;
130
131private:
132 void on_state_change_ack(message::ChangeStateAck &);
133 void on_child_init_failure(size_t actor_index);
134 void dispatch(Message &);
135 void on_child_down(size_t actor_index);
136 void init_child(size_t actor_index);
137 void start_actor(size_t actor_index);
138 size_t process_watchdog();
139 bool check_child_state(State subject, bool skip_self);
140};
141
145template <size_t HandlersCount, typename... Actors>
147 static_assert(HandlersCount >= SupervisorBase::min_handlers_amount,
148 "no enough handlers");
149
150 Supervisor()
151 : SupervisorBase(reinterpret_cast<char *>(&backends), HandlersCount,
153 actors[0] = this;
154 fill_actor<0>();
155 }
156
158 template <size_t ChildIndex> auto get_child() {
159 return &std::get<ChildIndex>(children);
160 }
161
162protected:
164 using ActorsList = std::tuple<Actors...>;
165
167 static constexpr size_t children_count = std::tuple_size_v<ActorsList>;
168
171
174
178
181
182private:
183 template <size_t ChildIndex> void fill_actor() {
184 if constexpr (ChildIndex < children_count) {
185 actors[ChildIndex + 1] = get_child<ChildIndex>();
186 fill_actor<ChildIndex + 1>();
187 }
188 }
189
190};
191
192template <typename Ctx, typename MessageType, typename... Args>
193bool ActorBase::send(size_t queue_index, Args... args) {
194 auto &queue = supervisor->queue;
195 if constexpr (std::is_same_v<Ctx, ctx::thread>) {
196 ROTOR_LIGHT_DISABLE_INTERRUPTS();
197 }
198 auto result =
199 queue->put<MessageType>(queue_index, std::forward<Args>(args)...);
200 if constexpr (std::is_same_v<Ctx, ctx::thread>) {
201 ROTOR_LIGHT_ENABLE_INTERRUPTS();
202 }
203 return result;
204}
205
206template <typename Ctx>
207EventId ActorBase::add_event(Duration delta, Callback callback, void *data) {
208 assert(supervisor->now && supervisor->planner);
209 auto when = supervisor->now() + delta;
210 return supervisor->planner->add_event<Ctx>(when, callback, data);
211}
212
213} // namespace rotor_light
runtime info about message subscription handler
Definition: actor.hpp:42
base interface and implementation for all actors, including supervisors
Definition: actor.hpp:19
bool send(size_t queue_index, Args... args)
emplaces new message into appropriate queue
Definition: supervisor.hpp:193
EventId add_event(Duration delta, Callback callback, void *data)
Definition: supervisor.hpp:207
static constexpr size_t min_handlers_amount
Definition: actor.hpp:55
SupervisorBase * supervisor
Definition: actor.hpp:180
root supervisor initialization tuple
Definition: context.hpp:18
base class for all rotor-light messages
Definition: message.hpp:22
bookeeper of future events
Definition: planner.hpp:59
EventId add_event(TimePoint when, Callback callback, void *data)
records the new event
Definition: planner.hpp:73
base class for meta-queue (list of queues, ordered by priorities))
Definition: queue.hpp:124
base interface and implementation for all supervisors
Definition: supervisor.hpp:29
uint8_t bind(ActorId initial_value, SupervisorBase *supervisor, Context &context) override
size_t actors_count
Definition: supervisor.hpp:120
PlannerBase * get_planner()
Definition: supervisor.hpp:101
ActorBase ** actors
Definition: supervisor.hpp:114
virtual void bind(Context &context, ActorId value=0)
NowFunction now
Definition: supervisor.hpp:129
void start(bool poll_timer=false)
starts all actors (initialize, wait confirmation etc.)
static constexpr size_t min_handlers_amount
Definition: supervisor.hpp:34
QueueBase * queue
Definition: supervisor.hpp:123
virtual void on_refhesh_timer(message::RefreshTime &)
void advance_stop() override
void advance_init() override
void advance_start() override
void initialize() override
SupervisorBase(char *backends, size_t backends_count, ActorBase **actors, details::ChildState *states, size_t actors_count)
PlannerBase * planner
Definition: supervisor.hpp:126
details::ChildState * states
Definition: supervisor.hpp:117
QueueBase * get_queue()
Definition: supervisor.hpp:45
convenient templated base class for supervisor, which owns (stores) all it's child-actors
Definition: supervisor.hpp:146
ActorBase::Handler backends[HandlersCount]
Definition: supervisor.hpp:173
auto get_child()
Definition: supervisor.hpp:158
details::ChildState children_states_holder[children_count+1]
Definition: supervisor.hpp:180
std::tuple< Actors... > ActorsList
Definition: supervisor.hpp:164
static constexpr size_t children_count
Definition: supervisor.hpp:167
ActorsList children
Definition: supervisor.hpp:170
ActorBase * actors[children_count+1]
Definition: supervisor.hpp:177
wrapper for holding child states in supervisor
Definition: supervisor.hpp:21
State down_state
Definition: supervisor.hpp:23
State Change confirmation, from actor to supervisor.
Definition: messages.hpp:32
Idle message, refreshes time and triggers expired timers.
Definition: messages.hpp:53