rotor_light
real-time C++ actor micro-framework for embedded systems, supervisable
actor.hpp
1// SPDX-License-Identifier: MIT
2// SPDX-FileCopyrightText: 2022 Ivan Baidakou
3
4#pragma once
5
6#include "context.hpp"
7#include "definitions.hpp"
8#include "messages.hpp"
9#include <cassert>
10
11namespace rotor_light {
12
13struct SupervisorBase;
14struct QueueBase;
15
19struct ActorBase {
21 using GenericMethod = void (ActorBase::*)(Message &);
22
25 template <typename T> struct handler_traits {};
26
27 template <typename A, typename M> struct handler_traits<void (A::*)(M &)> {
29 using FinalMessage = M;
30
32 using Backend = A;
33 };
34
35 struct Handler;
36
38 using MethodEntry = void (*)(Message &, ActorBase &, Handler &);
39
42 struct Handler {
45
47 MessageTypeId message_id;
48
51 };
52
55 static constexpr size_t min_handlers_amount = 1;
56
57 ActorBase(const ActorBase &) = delete;
58 ActorBase(ActorBase &&) = delete;
59
64 virtual void initialize();
65
68 virtual uint8_t bind(ActorId initial_value, SupervisorBase *supervisor,
69 Context &context);
70
72 inline ActorId get_id() const { return id; }
73
75 inline State get_state() const { return state; }
76
78 inline FailPolicy get_fail_policy() const { return fail_policy; }
79
81 inline void set_fail_policy(FailPolicy value) { fail_policy = value; }
82
85 void stop();
86
93 template <typename Ctx>
94 EventId add_event(Duration delta, Callback callback, void *data);
95
97 void cancel_event(EventId event_id);
98
108 template <typename Ctx, typename MessageType, typename... Args>
109 bool send(size_t queue_index, Args... args);
110
115 template <typename Method> void subscribe(Method method) {
116 assert(state == State::off);
117 assert(backend_idx < (int)backends_count);
118 auto ptr = backends_ptr + ++backend_idx * sizeof(Handler);
119 make_handler(method, *reinterpret_cast<Handler *>(ptr));
120 }
121
122protected:
126 ActorBase(char *backends, size_t backends_count);
127
141 virtual void advance_init();
142
150 virtual void advance_start();
151
162 virtual void advance_stop();
163
165 ActorId id;
166
174 ActorId mask;
175
177 State state = State::off;
178
181
183 FailPolicy fail_policy;
184
185private:
186 void on_state_change(message::ChangeState &);
187
188 template <typename Method>
189 void make_handler(Method &method, Handler &handler) {
190 using traits = handler_traits<Method>;
191 using FinalMessage = typename traits::FinalMessage;
192 using Backend = typename traits::Backend;
193
194 handler.message_id = FinalMessage::type_id;
195 handler.entry = [](Message &message, ActorBase &actor, Handler &handler) {
196 auto &final_message = static_cast<FinalMessage &>(message);
197 auto &backend = static_cast<Backend &>(actor);
198 (backend.*reinterpret_cast<Method &>(handler.method))(final_message);
199 };
200 handler.method = reinterpret_cast<GenericMethod &>(method);
201 }
202
203 char *backends_ptr;
204 size_t backends_count;
205 int backend_idx;
206
207 friend struct SupervisorBase;
208};
209
212template <size_t HandlersCount> struct Actor : ActorBase {
213 static_assert(HandlersCount >= Actor::min_handlers_amount,
214 "no enough handlers");
215 Actor() : ActorBase(reinterpret_cast<char *>(&backends), HandlersCount) {}
216
219};
220
221} // namespace rotor_light
runtime info about message subscription handler
Definition: actor.hpp:42
MessageTypeId message_id
holds message_id to do runtime message matching
Definition: actor.hpp:47
MethodEntry entry
Method entry item.
Definition: actor.hpp:50
GenericMethod method
holds pointer-to-member-function for message processing
Definition: actor.hpp:44
A Backend
final actor type
Definition: actor.hpp:32
M FinalMessage
messsage type
Definition: actor.hpp:29
helps method signature extraction
Definition: actor.hpp:25
base interface and implementation for all actors, including supervisors
Definition: actor.hpp:19
ActorId mask
Definition: actor.hpp:174
void subscribe(Method method)
Definition: actor.hpp:115
State state
Definition: actor.hpp:177
void(ActorBase::*)(Message &) GenericMethod
alias for generic message handler
Definition: actor.hpp:21
virtual void initialize()
FailPolicy fail_policy
Definition: actor.hpp:183
bool send(size_t queue_index, Args... args)
emplaces new message into appropriate queue
Definition: supervisor.hpp:193
ActorId get_id() const
Definition: actor.hpp:72
virtual uint8_t bind(ActorId initial_value, SupervisorBase *supervisor, Context &context)
FailPolicy get_fail_policy() const
Definition: actor.hpp:78
void set_fail_policy(FailPolicy value)
Definition: actor.hpp:81
State get_state() const
Definition: actor.hpp:75
virtual void advance_init()
EventId add_event(Duration delta, Callback callback, void *data)
Definition: supervisor.hpp:207
void(*)(Message &, ActorBase &, Handler &) MethodEntry
alias for method entry, enough to actually perfrom message delivery
Definition: actor.hpp:38
ActorBase(char *backends, size_t backends_count)
void cancel_event(EventId event_id)
static constexpr size_t min_handlers_amount
Definition: actor.hpp:55
SupervisorBase * supervisor
Definition: actor.hpp:180
ActorId id
Definition: actor.hpp:165
virtual void advance_stop()
virtual void advance_start()
convenient templated base class for user-defined actors
Definition: actor.hpp:212
ActorBase::Handler backends[HandlersCount]
Definition: actor.hpp:218
root supervisor initialization tuple
Definition: context.hpp:18
base class for all rotor-light messages
Definition: message.hpp:22
base interface and implementation for all supervisors
Definition: supervisor.hpp:29
State Change command, from supervisor/actor to actor.
Definition: messages.hpp:14