有限状态机通常用来描述一个对象在其生命周期中的状态变化,以及对外界的刺激(条件改变)做出响应进而进入下一个状态,最经典就是TCP状态转移。

有限状态机 - 图1
这里要实现的是一种通用状态机,可以Send事件,每一个状态可以响应自己注册的事件,同时也可以通过自身或者事件来改变状态机的状态。

  1. Contex类:
  2. CreateState() 接口,用于创建状态机和父状态机关系
  3. Update() 接口,外部驱动状态机函数
  4. SendEvent() 同步发送事件到当前状态,能发送任意数据到状态中处理
  5. SendAsyncEvent() 异步发送事件到当前状态,能发送任意数据到状态中处理
  6. State
  7. virtual void start(){} // 状态开始处理 子类实现
  8. virtual void update(){} // update处理 子类实现
  9. virtual void stop(){} // 状态结束处理 子类实现
  10. void set_event_func(); // 设置事件处理回调函数,子类绑定

框架

框架实现如下:

context.h

  1. #ifndef _CONTEXT_H_
  2. #define _CONTEXT_H_
  3. #include "Event.h"
  4. #include <string>
  5. #include <unordered_map>
  6. #include <thread>
  7. namespace HsmState
  8. {
  9. class State;
  10. struct NodeState
  11. {
  12. NodeState& operator = (const NodeState& n)
  13. {
  14. _state = n._state;
  15. _father_name = n._father_name;
  16. return *this;
  17. }
  18. State* _state;
  19. std::string _father_name;
  20. };
  21. class Context
  22. {
  23. public:
  24. friend class State;
  25. Context();
  26. ~Context();
  27. // 开始状态机
  28. bool Start(std::string name);
  29. // 创建一个状态
  30. // [in] state 状态对象,在Context销毁时,内部释放state
  31. // [in] name 状态名称,为空名称为typedname的值
  32. // [in] father_name 父状态的名称
  33. // [out] 返回state
  34. State* CreateState(State* state, std::string name, std::string father_name = "");
  35. // 更新当前状态
  36. void Update();
  37. // 同步事件
  38. // 发送一个事件,提供给root状态和当前状态处理
  39. // 如果当前状态是子状态,则还会给父状态处理
  40. void SendEvent(EventData event_data);
  41. // 异步事件
  42. void SendAsyncEvent(EventData event_data);
  43. // 获取当前状态名称
  44. std::string GetCurStateName();
  45. private:
  46. // 状态切换
  47. void TransForState(std::string name);
  48. // 递归send
  49. void RecursiveSend(NodeState& node_state, EventData& event_data);
  50. std::unordered_map<std::string, NodeState> _states; // 状态列表
  51. NodeState _cur_node_state; // 当前状态名
  52. std::string _cur_name;
  53. std::string _root_name; // 根状态名
  54. };
  55. }
  56. #endif // !STATE_H_

context.cpp

  1. #include "Context.h"
  2. #include "State.h"
  3. namespace HsmState
  4. {
  5. Context::Context()
  6. {
  7. }
  8. Context::~Context()
  9. {
  10. for (auto iter : _states)
  11. {
  12. if (iter.second._state)
  13. {
  14. delete iter.second._state;
  15. iter.second._state = nullptr;
  16. }
  17. }
  18. _states.clear();
  19. }
  20. // 开始状态机
  21. bool Context::Start(std::string name)
  22. {
  23. std::unordered_map<std::string, NodeState>::iterator iter_map = _states.find(name);
  24. if (iter_map != _states.end())
  25. {
  26. _cur_node_state = iter_map->second;
  27. _cur_name = iter_map->first;
  28. iter_map->second._state->start();
  29. }
  30. return false;
  31. }
  32. // 创建一个状态
  33. // [in] state 状态对象,在Context销毁时,内部释放state
  34. // [in] name 状态名称,为空名称为typedname的值
  35. // [in] father_name 父状态的名称
  36. // [out] 返回state
  37. State* Context::CreateState(State* state, std::string name, std::string father_name)
  38. {
  39. NodeState node_state;
  40. node_state._state = state;
  41. node_state._state->SetContext(this);
  42. node_state._father_name = father_name;
  43. _states[name] = node_state;
  44. return state;
  45. }
  46. // 更新当前状态
  47. void Context::Update()
  48. {
  49. _cur_node_state._state->update();
  50. }
  51. // 同步事件
  52. // 发送一个事件,提供给root状态和当前状态处理
  53. // 如果当前状态是子状态,则还会给父状态处理
  54. void Context::SendEvent(EventData event_data)
  55. {
  56. RecursiveSend(_cur_node_state, event_data);
  57. }
  58. // 异步事件
  59. void Context::SendAsyncEvent(EventData event_data)
  60. {
  61. // todo 待实现
  62. }
  63. std::string Context::GetCurStateName()
  64. {
  65. return _cur_name;
  66. }
  67. // 递归send
  68. void Context::RecursiveSend(NodeState& node_state, EventData& event_data)
  69. {
  70. EventDeal event_deal = node_state._state->RunEventFunc(event_data);
  71. if (event_deal == keep_on
  72. && !node_state._father_name.empty())
  73. {
  74. std::unordered_map<std::string, NodeState>::iterator iter_map = _states.find(node_state._father_name);
  75. if (iter_map != _states.end())
  76. {
  77. RecursiveSend(iter_map->second, event_data);
  78. }
  79. }
  80. }
  81. void Context::TransForState(std::string name)
  82. {
  83. std::string str_name = std::string(name);
  84. std::unordered_map<std::string, NodeState>::iterator iter_map = _states.find(str_name);
  85. if (iter_map != _states.end())
  86. {
  87. // 停止上一个状态
  88. _cur_node_state._state->stop();
  89. // 初始化下一个状态
  90. _cur_node_state = iter_map->second;
  91. _cur_name = iter_map->first;
  92. _cur_node_state._state->start();
  93. }
  94. }
  95. }

state.h

  1. #ifndef _STATE_H_
  2. #define _STATE_H_
  3. #include "Event.h"
  4. #include<functional>
  5. #include<string>
  6. namespace HsmState
  7. {
  8. class Context;
  9. class State
  10. {
  11. public:
  12. // 进入状态时调用,子类重写
  13. virtual void start(){}
  14. // 更新状态,可以由外部周期性调用
  15. virtual void update(){}
  16. // 停止状态是调用,子类重写
  17. virtual void stop(){}
  18. // 设置事件响应回调函数
  19. void set_event_func(std::function<EventDeal(EventData&)> func);
  20. EventDeal RunEventFunc(EventData& event_data);
  21. void SetContext(Context* context);
  22. // 切换状态
  23. // [in] name 状态名称
  24. void TransState(std::string name);
  25. private:
  26. std::function<EventDeal(EventData&)> _event_func;
  27. Context *_context;
  28. };
  29. }
  30. #endif // !STATE_H_

state.cpp

  1. #include "Context.h"
  2. #include "State.h"
  3. namespace HsmState
  4. {
  5. // 设置时间响应回调函数
  6. void State::set_event_func(std::function<EventDeal(EventData&)> func)
  7. {
  8. _event_func = func;
  9. }
  10. EventDeal State::RunEventFunc(EventData& event_data)
  11. {
  12. if (_event_func == nullptr)
  13. return keep_on;
  14. return _event_func(event_data);
  15. }
  16. void State::SetContext(Context* context)
  17. {
  18. _context = context;
  19. }
  20. void State::TransState(std::string name)
  21. {
  22. _context->TransForState(name);
  23. }
  24. }

event.h

  1. #pragma once
  2. namespace HsmState
  3. {
  4. enum EventDeal
  5. {
  6. tail = 0, // 事件结束处理
  7. keep_on // 事件继续传递
  8. };
  9. // 事件数据
  10. class EventData
  11. {
  12. public:
  13. EventData(int event_type)
  14. {
  15. _event_type = event_type;
  16. _data = nullptr;
  17. }
  18. template <class T>
  19. void SetData(T* t)
  20. {
  21. _data = t;
  22. }
  23. template <class T>
  24. T* GetData()
  25. {
  26. return (T*)_data;
  27. }
  28. int _event_type;
  29. private:
  30. void* _data;
  31. };
  32. }

应用举例

假如一个人一天生活状态变化:
有限状态机 - 图2
则OneDayState.cpp

  1. #include "Context.h"
  2. #include "State.h"
  3. #include <thread>
  4. #include <chrono>
  5. #include <iostream>
  6. #include <functional>
  7. using namespace HsmState;
  8. bool run = true;
  9. enum EventS
  10. {
  11. belazy = 0, // 偷懒事件
  12. };
  13. // 开始状态
  14. class StartState : public State
  15. {
  16. public :
  17. void start()
  18. {
  19. std::cout << "StartState start" << std::endl;
  20. }
  21. void stop()
  22. {
  23. std::cout << "StartState stop" << std::endl;
  24. }
  25. void update()
  26. {
  27. time++;
  28. if (time == 10)
  29. {
  30. TransState("HungerState");
  31. }
  32. }
  33. int time = 0;
  34. };
  35. // 饥饿状态
  36. class HungerState : public State
  37. {
  38. public:
  39. void start()
  40. {
  41. std::cout << "HungerState start" << std::endl;
  42. }
  43. void stop()
  44. {
  45. std::cout << "HungerState stop" << std::endl;
  46. }
  47. void update()
  48. {
  49. time++;
  50. if (time == 10)
  51. {
  52. TransState("Dinner");
  53. }
  54. }
  55. int time = 0;
  56. };
  57. class Dinner : public State
  58. {
  59. public:
  60. void start()
  61. {
  62. std::cout << "Dinner start" << std::endl;
  63. }
  64. void stop()
  65. {
  66. std::cout << "Dinner stop" << std::endl;
  67. }
  68. void update()
  69. {
  70. TransState("DoTheCookingState");
  71. }
  72. };
  73. // 做饭状态
  74. class DoTheCookingState : public State
  75. {
  76. public:
  77. void start()
  78. {
  79. std::cout << "DoTheCookingState start" << std::endl;
  80. }
  81. void stop()
  82. {
  83. std::cout << "DoTheCookingState stop" << std::endl;
  84. }
  85. void update()
  86. {
  87. time++;
  88. if (time == 60)
  89. {
  90. TransState("EatState");
  91. }
  92. }
  93. int time = 0;
  94. };
  95. // 吃饭状态
  96. class EatState : public State
  97. {
  98. public:
  99. void start()
  100. {
  101. std::cout << "EatState start" << std::endl;
  102. }
  103. void stop()
  104. {
  105. std::cout << "EatState stop" << std::endl;
  106. }
  107. void update()
  108. {
  109. time++;
  110. if (time == 5)
  111. {
  112. TransState("SleepState");
  113. }
  114. }
  115. int time = 0;
  116. };
  117. // 饭后睡觉状态
  118. class SleepState : public State
  119. {
  120. public:
  121. void start()
  122. {
  123. std::cout << "SleepState start" << std::endl;
  124. }
  125. void stop()
  126. {
  127. std::cout << "SleepState stop" << std::endl;
  128. }
  129. void update()
  130. {
  131. time++;
  132. if (time == 30)
  133. {
  134. TransState("WorkState");
  135. }
  136. }
  137. int time = 0;
  138. };
  139. // 工作状态
  140. class WorkState : public State
  141. {
  142. public:
  143. void start()
  144. {
  145. std::cout << "WorkState start" << std::endl;
  146. std::function<EventDeal(EventData&)> func = std::bind(&WorkState::DealEvent, this, std::placeholders::_1);;
  147. set_event_func(func);
  148. }
  149. void stop()
  150. {
  151. std::cout << "WorkState stop" << std::endl;
  152. }
  153. EventDeal DealEvent(EventData &event_data)
  154. {
  155. switch ((EventS)event_data._event_type)
  156. {
  157. case belazy:
  158. TransState("LoafOnAJob");
  159. break;
  160. default:
  161. break;
  162. }
  163. return keep_on;
  164. }
  165. void update()
  166. {
  167. time++;
  168. if (time == 180)
  169. {
  170. run = false;
  171. }
  172. }
  173. int time = 0;
  174. };
  175. // 工作摸鱼状态
  176. class LoafOnAJob : public State
  177. {
  178. public:
  179. void start()
  180. {
  181. time = 0;
  182. std::cout << "LoafOnAJob start" << std::endl;
  183. }
  184. void stop()
  185. {
  186. std::cout << "LoafOnAJob stop" << std::endl;
  187. }
  188. void update()
  189. {
  190. time++;
  191. if (time == 10)
  192. {
  193. TransState("WorkState");
  194. }
  195. }
  196. int time = 0;
  197. };
  198. // 对象工厂
  199. class Factory
  200. {
  201. public :
  202. static State* CreateState(Context* context, std::string name, std::string parent_name = "")
  203. {
  204. State* state = nullptr;
  205. if (name == "StartState")
  206. {
  207. state = new StartState();
  208. }
  209. else if (name == "HungerState")
  210. {
  211. state = new HungerState();
  212. }
  213. else if (name == "Dinner")
  214. {
  215. state = new Dinner();
  216. }
  217. else if (name == "DoTheCookingState")
  218. {
  219. state = new DoTheCookingState();
  220. }
  221. else if (name == "EatState")
  222. {
  223. state = new EatState();
  224. }
  225. else if (name == "SleepState")
  226. {
  227. state = new SleepState();
  228. }
  229. else if (name == "WorkState")
  230. {
  231. state = new WorkState();
  232. }
  233. else if (name == "LoafOnAJob")
  234. {
  235. state = new LoafOnAJob();
  236. }
  237. context->CreateState(state, name, parent_name);
  238. return state;
  239. }
  240. };
  241. int main()
  242. {
  243. Context* context = new Context();
  244. // 创建状态机
  245. Factory::CreateState(context, "StartState");
  246. Factory::CreateState(context, "HungerState");
  247. Factory::CreateState(context, "Dinner");
  248. Factory::CreateState(context, "DoTheCookingState", "Dinner");
  249. Factory::CreateState(context, "EatState", "Dinner");
  250. Factory::CreateState(context, "SleepState");
  251. Factory::CreateState(context, "WorkState");
  252. Factory::CreateState(context, "LoafOnAJob");
  253. // 开始状态机
  254. context->Start("StartState");
  255. int time = 0;
  256. while (run)
  257. {
  258. time++;
  259. std::this_thread::sleep_for(
  260. std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::milliseconds(10)));
  261. context->Update();
  262. // 如果为工作状态,每隔60分钟发出偷懒事件
  263. if (context->GetCurStateName() == "WorkState"
  264. && time % 60 == 0)
  265. {
  266. EventData e = EventData((int)belazy);
  267. context->SendEvent(e);
  268. }
  269. }
  270. if (context)
  271. {
  272. delete context;
  273. context = nullptr;
  274. }
  275. std::cout << "state close" << std::endl;
  276. return 0;
  277. }

有限状态机 - 图3