1 /*
2  * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
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 #ifndef STATE_MACHINE_H
17 #define STATE_MACHINE_H
18 
19 #include <array>
20 #include <map>
21 #include <string>
22 #include "base_def.h"
23 #include "message.h"
24 
25 namespace utility {
26 class StateMachine {
27 public:
28     class State {
29     public:
30         /**
31          * @brief Construct a new State object.
32          * @param name State's name.
33          * @param statemachine State is owned by which StateMachine.
34          * @param parent State's parent state.
35          * @since 6
36          */
State(const std::string & name,StateMachine & statemachine)37         explicit State(const std::string &name, StateMachine &statemachine)
38             : name_(name), statemachine_(statemachine){};
39 
40         /**
41          * @brief Construct a new State object.
42          * @param name State's name.
43          * @param statemachine State is owned by which StateMachine.
44          * @param parent State's parent state.
45          * @since 6
46          */
State(const std::string & name,StateMachine & statemachine,State & parent)47         explicit State(const std::string &name, StateMachine &statemachine, State &parent)
48             : name_(name), statemachine_(statemachine), parent_(&parent){};
49 
50         /**
51          * @brief Destroy the State object
52          * @since 6
53          */
~State()54         virtual ~State(){};
55 
56         /**
57          * @brief Get State's name.
58          * @return State's name.
59          * @since 6
60          */
Name()61         const std::string &Name() const
62         {
63             return name_;
64         };
65 
66         /**
67          * @brief Transition to another state.
68          * @param name Another state's name.
69          */
Transition(const std::string & name)70         void Transition(const std::string &name)
71         {
72             statemachine_.Transition(name);
73         };
74 
75     private:
76         State() = delete;
77 
78         /**
79          * @brief Operation should be executed when Entry the state.
80          * @since 6
81          */
82         virtual void Entry() = 0;
83 
84         /**
85          * @brief Operation should be executed when Exit the state.
86          * @since 6
87          */
88         virtual void Exit() = 0;
89 
90         virtual bool Dispatch(const Message &msg) = 0;
91 
92         std::string name_ {""};
93         StateMachine &statemachine_;
94         State* parent_ {nullptr};
95 
96         friend class StateMachine;
97         BT_DISALLOW_COPY_AND_ASSIGN(State);
98     };
99 
100     /**
101      * @brief Construct a new State Machine object
102      * @since 6
103      */
StateMachine()104     StateMachine() {};
105 
106     /**
107      * @brief Destroy the State Machine object, type is virtual.
108      * @since 6
109      */
~StateMachine()110     virtual ~StateMachine() {};
111 
112     /**
113      * @brief Move unique_ptr of state to StateMachine.
114      * @param state State pointer.
115      * @since 6
116      */
117     void Move(std::unique_ptr<State> &state);
118 
119     /**
120      * @brief Transation to init state.
121      * @param name Init state's name.
122      * @since 6
123      */
124     void InitState(const std::string &name);
125 
126     /**
127      * @brief StateMachine process message
128      * @param msg message reference.
129      * @since 6
130      */
131     bool ProcessMessage(const Message &msg) const;
132 
133     /**
134      * @brief Get the State object
135      * @return const State &
136      * @since 6
137      */
138     const State *GetState() const;
139 
140 private:
141     const static int STACK_DEPTH = 5;
142     void Transition(const std::string &name);
143     inline int GetStateDepth(State &state);
144 
145     int top_ {0};
146     State* current_ {nullptr};
147     std::array<State*, STACK_DEPTH> stack_ {};
148     std::map<std::string, std::unique_ptr<State>> states_ {};
149 
150     BT_DISALLOW_COPY_AND_ASSIGN(StateMachine);
151 };
152 }  // namespace utility
153 
154 #endif  // STATE_MACHINE_H