SMACC2
Loading...
Searching...
No Matches
smacc_asynchronous_client_behavior.hpp
Go to the documentation of this file.
1// Copyright 2021 RobosoftAI Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/*****************************************************************************************************************
16 *
17 * Authors: Pablo Inigo Blasco, Brett Aldrich
18 *
19 ******************************************************************************************************************/
20
21#pragma once
22#include <future>
25
26namespace smacc2
27{
28template <typename AsyncCB, typename Orthogonal>
29struct EvCbFinished : sc::event<EvCbFinished<AsyncCB, Orthogonal>>
30{
31};
32
33template <typename AsyncCB, typename Orthogonal>
34struct EvCbSuccess : sc::event<EvCbSuccess<AsyncCB, Orthogonal>>
35{
36};
37
38template <typename AsyncCB, typename Orthogonal>
39struct EvCbFailure : sc::event<EvCbFailure<AsyncCB, Orthogonal>>
40{
41};
42
43// INTRODUCTION: Conceptually, AsynchronousClientBehaviors start in parallel on state entry.
44// Asnchronous client behaviors are used when the onEntry or onExit function execution could be too much slow and
45// could block the state machine thread.
46// AsynchronousClientBehaviors are related with the concept orthogonality of Smacc State Machines.
47// ASYNCHRONOUS STATE MACHINES DESIGN NOTES: Asynchronous behaviors can safely post events and use its local methods,
48// but the interaction with other components or elements of
49// the state machine is not by-default thread safe and must be manually implemented. For example, if some element of the architecture
50// (components, states, clients) need to access to this behavior client information it is needed to implement a mutex for the internal
51// state of this behavior. Other example: if this behavior access to some component located in other thread, it is also may be needed
52// to some mutex for that component
53// ALTERNATIVE: for long duration behaviors: using default-synchromous SmaccClientBehaviors with the update method
54
56{
57public:
58 template <typename TOrthogonal, typename TSourceObject>
60
62
63 template <typename TCallback, typename T>
64 boost::signals2::connection onSuccess(TCallback callback, T * object);
65
66 template <typename TCallback, typename T>
67 boost::signals2::connection onFinished(TCallback callback, T * object);
68
69 template <typename TCallback, typename T>
70 boost::signals2::connection onFailure(TCallback callback, T * object);
71
72 void requestForceFinish();
73
74 // executes onExit in a new thread
75 void executeOnEntry() override;
76
77 // executes onExit in a new thread, waits first onEntry thread if it is still running
78 void executeOnExit() override;
80
81protected:
82 void postSuccessEvent();
83 void postFailureEvent();
84
85 virtual void dispose() override;
86
89 // All asyncrhonous client behaviors should implement the ability of interrupting the onEntry thread.
90 // to avoid blocking the state machine.
91
92 // inline bool isShutdownRequested() { return isShutdownRequested_; }
94
95private:
96 void waitFutureIfNotFinished(std::optional<std::future<int>> & threadfut, bool requestFinish);
97
98 std::optional<std::future<int>> onEntryThread_;
99 std::optional<std::future<int>> onExitThread_;
100
101 std::function<void()> postFinishEventFn_;
102 std::function<void()> postSuccessEventFn_;
103 std::function<void()> postFailureEventFn_;
104
108
110};
111} // namespace smacc2
112
bool isShutdownRequested()
onEntry is executed in a new thread. However the current state cannot be left until the onEntry threa...
std::optional< std::future< int > > onExitThread_
std::optional< std::future< int > > onEntryThread_
boost::signals2::connection onFinished(TCallback callback, T *object)
void waitFutureIfNotFinished(std::optional< std::future< int > > &threadfut, bool requestFinish)
boost::signals2::connection onSuccess(TCallback callback, T *object)
boost::signals2::connection onFailure(TCallback callback, T *object)