RTC Toolkit 6.0.0
Loading...
Searching...
No Matches
optimisable.hpp
Go to the documentation of this file.
1
11
12#ifndef RTCTK_COMPONENTFRAMEWORK_OPTIMISABLE_HPP
13#define RTCTK_COMPONENTFRAMEWORK_OPTIMISABLE_HPP
14
21
23namespace detail {
35public:
42 explicit OptimiseContext(const rad::cii::Request<std::string, std::string>& request)
43 : m_logger(GetLogger("rtctk")), m_request(request), m_arg() {
44 m_arg = JsonPayload::parse(m_request.GetRequestPayload());
45 }
46 OptimiseContext(OptimiseContext&&) noexcept = default;
47
51 const JsonPayload& GetArg() const noexcept {
52 return m_arg;
53 }
54
60 void SendReply() noexcept {
61 try {
62 m_request.SetReplyValue(STD_OK_REPLY);
63 } catch (const std::exception& exception) {
64 LOG4CPLUS_ERROR(
65 m_logger, "OptimiseContext::SendReply: Failed to send reply: " << exception.what());
66 } catch (...) {
67 LOG4CPLUS_ERROR(
68 m_logger,
69 "OptimiseContext::SendReply: Failed to send reply with unknown exception.");
70 }
71 }
72
78 void SendErrorReply(std::exception_ptr eptr) noexcept {
79 try {
80 m_request.SetException(RequestFailed(NestedExceptionPrinter(std::move(eptr)).Str()));
81 } catch (...) {
82 }
83 }
84
85private:
86 log4cplus::Logger& m_logger;
87
89 rad::cii::Request<std::string, std::string> m_request;
93 JsonPayload m_arg;
94};
95} // namespace detail
96
126template <typename Super>
127struct Optimisable : Super {
128 static_assert(std::is_base_of_v<RtcComponent, Super>, "'Optimisable' requires 'RtcComponent'");
129
134 class BizLogicIf : public Super::BizLogicIf {
135 public:
136 // Due to Doxygen limitations the multi-line @exception_basic command cannot have the '*'
137 // character on each line.
148 virtual void ActivityOptimising(StopToken st, const JsonPayload& arg) {
149 }
150
159 virtual bool GuardOptimisingAllowed(const JsonPayload& arg) {
160 return true;
161 }
162 };
163
167 class InputStage : public Super::InputStage {
168 public:
169 using Super::InputStage::InputStage;
170
171 void Start() override {
172 Super::InputStage::Start();
173
174 OptCmdsImpl::Register(this->m_replier, this->m_engine);
175 }
176 };
177
181 class OutputStage : public Super::OutputStage {
182 public:
183 OutputStage(StateMachineEngine& engine, BizLogicIf& bl) : Super::OutputStage(engine, bl) {
184 // Handlers ###################################################################
185
186 engine.RegisterRejectHandler<events::Optimise, RequestRejected>();
187
189 this->m_engine.PostEvent(std::make_unique<events::OptimiseDone>());
190 };
191
192 m_optimise_error_handler = [this](std::exception_ptr eptr) {
193 this->m_engine.PostEvent(std::make_unique<events::OptimiseError>(std::move(eptr)));
194 };
195
196 // No Disable in states ###############################################################
197
198 this->m_no_disable_in_states.emplace_back("On::Operational:Optimise:Busy");
199
200 // No Update in states ################################################################
201
202 this->m_no_update_in_states.emplace_back("On::Operational:Optimise:Busy");
203
204 // No Optimise in states ##############################################################
205
206 this->m_no_optimise_in_states.emplace_back("On:Update:Busy");
207
208 // Guards #####################################################################
209
210 engine.RegisterGuardStatic<events::Optimise>(
211 "GuardOptimisingAllowed", [this](const events::Optimise& ev) -> bool {
220 auto act_state = this->m_engine.GetState();
221 for (auto& s : m_no_optimise_in_states) {
222 if (act_state.find(s) != std::string::npos) {
223 return false;
224 }
225 }
226 detail::OptimiseContext ctx(ev.GetPayload());
227 if (static_cast<BizLogicIf&>(this->m_logic)
228 .GuardOptimisingAllowed(ctx.GetArg())) {
229 // Optimise is allowed so context is stored.
230 // If there's an active context (and correspondingly an active
231 // request being processed something have gone terribly wrong)
232 assert(!m_optimise_ctx);
233 m_optimise_ctx.emplace(std::move(ctx));
234 return true;
235 }
236 return false;
237 });
238
239 // Activities #####################################################################
240
241 engine.RegisterActivity(
242 "ActivityOptimising",
243 [this](StopToken stop_token) {
244 assert(m_optimise_ctx);
245 static_cast<BizLogicIf&>(this->m_logic)
246 .ActivityOptimising(stop_token, m_optimise_ctx->GetArg());
247 },
250
251 // Actions #####################################################################
252 engine.RegisterActionStatic<events::OptimiseDone>("ActionOptimisingDone",
253 [this](const events::OptimiseDone&) {
254 assert(m_optimise_ctx);
255 m_optimise_ctx->SendReply();
256 m_optimise_ctx.reset();
257 });
258
259 engine.RegisterActionStatic<events::OptimiseError>(
260 "ActionOptimisingFailed", [this](const events::OptimiseError& ev) {
261 m_optimise_ctx->SendErrorReply(ev.GetPayload());
262 m_optimise_ctx.reset();
263 });
264 }
265
266 protected:
267 std::optional<detail::OptimiseContext> m_optimise_ctx;
268 std::function<void()> m_optimise_success_handler;
269 std::function<void(std::exception_ptr)> m_optimise_error_handler;
270 std::list<std::string> m_no_optimise_in_states;
271 };
272
276 class ModelBuilder : public Super::ModelBuilder {
277 public:
278 explicit ModelBuilder(StateMachineEngine& engine) : Super::ModelBuilder(engine) {
279 // clang-format off
280 this->mm.ModStateType("On::Operational", Parallel);
281
282 this->mm.AddState(Composite, "On::Operational:Optimise:", "On::Operational");
283 this->mm.AddState(Initial, "On::Operational:Optimise:Initial", "On::Operational:Optimise:");
284 this->mm.AddState(Simple, "On::Operational:Optimise:Idle", "On::Operational:Optimise:");
285 this->mm.AddState(Simple, "On::Operational:Optimise:Busy", "On::Operational:Optimise:", "ActivityOptimising");
286
287 this->mm.AddTrans("On::Operational:Optimise:Initial" , "On::Operational:Optimise:Idle" );
288 this->mm.AddTrans("On::Operational:Optimise:Idle" , "On::Operational:Optimise:Busy", events::Optimise::ID, "GuardOptimisingAllowed");
289 this->mm.AddTrans("On::Operational:Optimise:Busy" , "On::Operational:Optimise:Idle", events::OptimiseDone::ID, "", "ActionOptimisingDone");
290 this->mm.AddTrans("On::Operational:Optimise:Busy" , "On::Operational:Optimise:Idle", events::OptimiseError::ID, "", "ActionOptimisingFailed");
291 // clang-format on
292 }
293 };
294};
295
296} // namespace rtctk::componentFramework
297
298#endif
Adapter object intended to be used in contexts without direct access to the output-stream object.
Definition exceptions.hpp:168
static void Register(CommandReplier &replier, StateMachineEngine &engine)
Definition optCmdsImpl.hpp:36
Business logic interface for Optimisable mixin.
Definition optimisable.hpp:134
virtual bool GuardOptimisingAllowed(const JsonPayload &arg)
Determines if optimising is possible at this time with the provided argument.
Definition optimisable.hpp:159
virtual void ActivityOptimising(StopToken st, const JsonPayload &arg)
Activity executed in its own thread that performs the requested optimisation.
Definition optimisable.hpp:148
void Start() override
Definition optimisable.hpp:171
ModelBuilder(StateMachineEngine &engine)
Definition optimisable.hpp:278
std::optional< detail::OptimiseContext > m_optimise_ctx
Definition optimisable.hpp:267
OutputStage(StateMachineEngine &engine, BizLogicIf &bl)
Definition optimisable.hpp:183
std::function< void()> m_optimise_success_handler
Definition optimisable.hpp:268
std::function< void(std::exception_ptr)> m_optimise_error_handler
Definition optimisable.hpp:269
std::list< std::string > m_no_optimise_in_states
Definition optimisable.hpp:270
Thrown if the command was accepted but the task to run failed.
Definition rtcComponent.hpp:52
Thrown if a command is not allowed in current state or guard.
Definition rtcComponent.hpp:39
Definition stateMachineEngine.hpp:34
void RegisterGuardStatic(const std::string &id, std::function< bool(const Event &)> guard)
Register guard for statically known event type.
Definition stateMachineEngine.hpp:125
void RegisterRejectHandler(const std::string &id, RejectMethod reject)
Register reject handler.
Definition stateMachineEngine.cpp:128
void RegisterActivity(const std::string &id, ActivityMethod activity, SuccessMethod on_success, FailureMethod on_failure)
Register activity.
Definition stateMachineEngine.cpp:120
void RegisterActionStatic(const std::string &id, std::function< void(const Event &)> action)
Register action for statically known event type.
Definition stateMachineEngine.hpp:92
Holds context necessary for processing a optimise request to completion.
Definition optimisable.hpp:34
const JsonPayload & GetArg() const noexcept
Definition optimisable.hpp:51
void SendErrorReply(std::exception_ptr eptr) noexcept
Send exceptional reply.
Definition optimisable.hpp:78
OptimiseContext(OptimiseContext &&) noexcept=default
void SendReply() noexcept
Sends hardcoded string reply.
Definition optimisable.hpp:60
OptimiseContext(const rad::cii::Request< std::string, std::string > &request)
Construct context with provided request.
Definition optimisable.hpp:42
Provides macros and utilities for exception handling.
log4cplus::Logger & GetLogger(const std::string &name="app")
Get handle to a specific logger.
Definition logger.cpp:191
Defines the JSON payload type JsonPayload.
Logging Support Library based on log4cplus.
Definition measurable.hpp:25
Definition commandReplier.cpp:21
@ Simple
Definition model.hpp:22
@ Composite
Definition model.hpp:22
@ Parallel
Definition model.hpp:22
@ Initial
Definition model.hpp:22
rad::StopToken StopToken
Definition stopToken.hpp:19
const std::string STD_OK_REPLY
Definition stdComponent.hpp:85
nlohmann::json JsonPayload
Type requirements:
Definition jsonPayload.hpp:24
Implementation of MAL commands for layer 'Optimisable'.
Lifecycle of a basic 'RtcComponent'.
A simple Stop Token.
Life cycle extension to make RtcComponent Optimisable.
Definition optimisable.hpp:127