tinyFSM源码阅读

0、什么是有限状态机

有限状态机(FSM)是一种数学模型,用于表示系统中不同状态之间的转换。FSM 由以下几部分组成:

  • 状态(State):表示系统的不同阶段。
  • 事件(Event):触发状态转换的条件。
  • 转换(Transition):在特定事件发生时,系统从一个状态转移到另一个状态。
  • 动作(Action):状态转换时执行的操作,通常在进入某个状态或从某个状态退出时发生。
    在很多嵌入式系统、游戏开发以及应用程序控制中,FSM 是一种非常实用的设计模式。它能够帮助我们清晰地设计出状态之间的转换和行为逻辑。

1、tinyFSM源码分析

TinyFSM 是一个极其轻量级的库。它专注于实现有限状态机的核心功能,并且避免了不必要的复杂性。因为代码行数比较少,因此直接将源码贴到下面,并将本人的理解以注释的形式添加到代码中,直接看代码

namespace tinyfsm
{

  // --------------------------------------------------------------------------

  struct Event { };

  // --------------------------------------------------------------------------

#ifdef TINYFSM_NOSTDLIB
  // remove dependency on standard library (silent fail!).
  // useful in conjunction with -nostdlib option, e.g. if your compiler
  // does not provide a standard library.
  // NOTE: this silently disables all static_assert() calls below!
  template<typename F, typename S>
  struct is_same_fsm { static constexpr bool value = true; };
#else
  // check if both fsm and state class share same fsmtype
  template<typename F, typename S>
  // std::is_same的作用是判断两个类型是不是一样的,下面语句的typename的主要作用是告诉编译器后面是一个类型
  struct is_same_fsm : std::is_same< typename F::fsmtype, typename S::fsmtype > { };
#endif

  template<typename S>
  struct _state_instance
  {
    using value_type = S;
    using type = _state_instance<S>;
    static S value;
  };

  template<typename S>
  // typename 告诉编译器后面是一个类型,这里实际是给静态变量分配空间
  typename _state_instance<S>::value_type _state_instance<S>::value;

  // --------------------------------------------------------------------------

  template<typename F>
  class Fsm
  {
  public:

    using fsmtype = Fsm<F>;
    using state_ptr_t = F *;

    static state_ptr_t current_state_ptr;

    // public, leaving ability to access state instance (e.g. on reset)
    template<typename S>
    // 获取定义的状态S的值
    static constexpr S & state(void) {
      static_assert(is_same_fsm<F, S>::value, "accessing state of different state machine");
      return _state_instance<S>::value;
    }

    template<typename S>
    // 检测状态机是不是在状态S
    static constexpr bool is_in_state(void) {
      static_assert(is_same_fsm<F, S>::value, "accessing state of different state machine");
      return current_state_ptr == &_state_instance<S>::value;
    }

  /// state machine functions
  public:

    // explicitely specialized in FSM_INITIAL_STATE macro
    static void set_initial_state();

    static void reset() { };

    static void enter() {
      current_state_ptr->entry();
    }

    static void start() {
      set_initial_state();
      enter();
    }

    template<typename E>
    static void dispatch(E const & event) {
      current_state_ptr->react(event);
    }


  /// state transition functions
  protected:
    // S 是要进入的状态
    template<typename S>
    void transit(void) {
      static_assert(is_same_fsm<F, S>::value, "transit to different state machine");
      current_state_ptr->exit();
      current_state_ptr = &_state_instance<S>::value;
      current_state_ptr->entry();
    }
    // 切换到 S 状态之前执行动作action_function
    template<typename S, typename ActionFunction>
    void transit(ActionFunction action_function) {
      static_assert(is_same_fsm<F, S>::value, "transit to different state machine");
      current_state_ptr->exit();
      // NOTE: do not send events in action_function definisions.
      action_function();
      current_state_ptr = &_state_instance<S>::value;
      current_state_ptr->entry();
    }
    // 满足条件condition_function时,切换到S,并执行action_function动作
    template<typename S, typename ActionFunction, typename ConditionFunction>
    void transit(ActionFunction action_function, ConditionFunction condition_function) {
      if(condition_function()) {
        transit<S>(action_function);
      }
    }
  };

  template<typename F>
  typename Fsm<F>::state_ptr_t Fsm<F>::current_state_ptr;

  // --------------------------------------------------------------------------
  // 这里是定义了FsmList,有一个特化版本template<> struct FsmList<>
  // 泛化版本,利用了模板递归技术,定义了各种递归方法,出口是特化版本
  template<typename... FF>
  struct FsmList;

  template<> struct FsmList<> {
    static void set_initial_state() { }
    static void reset() { }
    static void enter() { }
    template<typename E>
    static void dispatch(E const &) { }
  };

  template<typename F, typename... FF>
  struct FsmList<F, FF...>
  {
    using fsmtype = Fsm<F>;

    static void set_initial_state() {
      fsmtype::set_initial_state();
      FsmList<FF...>::set_initial_state();
    }

    static void reset() {
      F::reset();
      FsmList<FF...>::reset();
    }

    static void enter() {
      fsmtype::enter();
      FsmList<FF...>::enter();
    }

    static void start() {
      set_initial_state();
      enter();
    }

    template<typename E>
    static void dispatch(E const & event) {
      fsmtype::template dispatch<E>(event);
      FsmList<FF...>::template dispatch<E>(event);
    }
  };

  // --------------------------------------------------------------------------
  // 状态管理,技术和上面的技术一样
  template<typename... SS> struct StateList;
  template<> struct StateList<> {
    static void reset() { }
  };
  template<typename S, typename... SS>
  struct StateList<S, SS...>
  {
    static void reset() {
      _state_instance<S>::value = S();
      StateList<SS...>::reset();
    }
  };

  // --------------------------------------------------------------------------

  template<typename F>
  struct MooreMachine : tinyfsm::Fsm<F>
  {
    virtual void entry(void) { };  /* entry actions in some states */
    void exit(void) { };           /* no exit actions */
  };

  template<typename F>
  struct MealyMachine : tinyfsm::Fsm<F>
  {
    // input actions are modeled in react():
    // - conditional dependent of event type or payload
    // - transit<>(ActionFunction)
    void entry(void) { };  /* no entry actions */
    void exit(void) { };   /* no exit actions */
  };

} /* namespace tinyfsm */

// 这个宏的作用是设置有限状态机的初始状态
#define FSM_INITIAL_STATE(_FSM, _STATE)                               \
namespace tinyfsm {                                                   \
  template<> void Fsm< _FSM >::set_initial_state(void) {              \
    current_state_ptr = &_state_instance< _STATE >::value;            \
  }                                                                   \
}

#endif /* TINYFSM_HPP_INCLUDED */

2、使用实例

下面是tinyFsm库中的电梯的使用示例,代码不是很难理解,只添加了少量注释:

// moctor.hpp
struct FloorEvent : tinyfsm::Event
{
  int floor;
};
// 定义了3个事件
struct Call        : FloorEvent { };
struct FloorSensor : FloorEvent { };
struct Alarm       : tinyfsm::Event { };



// ----------------------------------------------------------------------------
// Elevator (FSM base class) declaration
//

class Elevator
: public tinyfsm::Fsm<Elevator>
{
  /* NOTE: react(), entry() and exit() functions need to be accessible
   * from tinyfsm::Fsm class. You might as well declare friendship to
   * tinyfsm::Fsm, and make these functions private:
   *
   * friend class Fsm;
   */
public:

  /* default reaction for unhandled events */
  void react(tinyfsm::Event const &) { };
 // 该状态机发生了上面的事件时,该如何反应
  virtual void react(Call        const &);
  virtual void react(FloorSensor const &);
  void         react(Alarm       const &);
 // 留给具体的状态去实现
  virtual void entry(void) { };  /* entry actions in some states */
  void         exit(void)  { };  /* no exit actions at all */

protected:

  static constexpr int initial_floor = 0;
  static int current_floor;
  static int dest_floor;
};
// -------------------------------
// moctor.cpp
// -------------------------------
class Stopped
: public Motor
{
  void entry() override {
    std::cout << "Motor: stopped" << std::endl;
    direction = 0;
  };
};

class Up
: public Motor
{
  void entry() override {
    std::cout << "Motor: moving up" << std::endl;
    direction = 1;
  };
};

class Down
: public Motor
{
  void entry() override {
    std::cout << "Motor: moving down" << std::endl;
    direction = -1;
  };
};


// ----------------------------------------------------------------------------
// Base State: default implementations
//

void Motor::react(MotorStop const &) {
  transit<Stopped>();
}

void Motor::react(MotorUp const &) {
  transit<Up>();
}

void Motor::react(MotorDown const &) {
  transit<Down>();
}

int Motor::direction{0};
// -------------------------------
// elevator.hpp
// -------------------------------
struct FloorEvent : tinyfsm::Event
{
  int floor;
};
// 定义3个事件
struct Call        : FloorEvent { };
struct FloorSensor : FloorEvent { };
struct Alarm       : tinyfsm::Event { };



// ----------------------------------------------------------------------------
// Elevator (FSM base class) declaration
//

class Elevator
: public tinyfsm::Fsm<Elevator>
{
  /* NOTE: react(), entry() and exit() functions need to be accessible
   * from tinyfsm::Fsm class. You might as well declare friendship to
   * tinyfsm::Fsm, and make these functions private:
   *
   * friend class Fsm;
   */
public:

  /* default reaction for unhandled events */
  void react(tinyfsm::Event const &) { };
 // 状态机处理对应的动作,需函数留给子类实现
  virtual void react(Call        const &);
  virtual void react(FloorSensor const &);
  void         react(Alarm       const &);

  virtual void entry(void) { };  /* entry actions in some states */
  void         exit(void)  { };  /* no exit actions at all */

protected:

  static constexpr int initial_floor = 0;
  static int current_floor;
  static int dest_floor;
};
// -------------------------------
// elevator.cpp
// -------------------------------
// State: Panic
//

class Panic
: public Elevator
{
  void entry() override {
    // 发送时间给Motor状态机
    send_event(MotorStop());
  }
};


// ----------------------------------------------------------------------------
// State: Moving
//

class Moving
: public Elevator
{
  void react(FloorSensor const & e) override {
    int floor_expected = current_floor + Motor::getDirection();
    if(floor_expected != e.floor)
    {
      std::cout << "Floor sensor defect (expected " << floor_expected << ", got " << e.floor << ")" << std::endl;
      transit<Panic>(CallMaintenance);
    }
    else
    {
      std::cout << "Reached floor " << e.floor << std::endl;
      current_floor = e.floor;
      if(e.floor == dest_floor)
        transit<Idle>();
    }
  };
};


// ----------------------------------------------------------------------------
// State: Idle
//

class Idle
: public Elevator
{
  void entry() override {
    send_event(MotorStop());
  }

  void react(Call const & e) override {
    dest_floor = e.floor;

    if(dest_floor == current_floor)
      return;

    /* lambda function used for transition action */
    auto action = [] { 
      if(dest_floor > current_floor)
        send_event(MotorUp());
      else if(dest_floor < current_floor)
        send_event(MotorDown());
    };

    transit<Moving>(action);
  };
};


// ----------------------------------------------------------------------------
// Base state: default implementations
//

void Elevator::react(Call const &) {
  std::cout << "Call event ignored" << std::endl;
}

void Elevator::react(FloorSensor const &) {
  std::cout << "FloorSensor event ignored" << std::endl;
}

void Elevator::react(Alarm const &) {
  transit<Panic>(CallFirefighters);
}

int Elevator::current_floor = Elevator::initial_floor;
int Elevator::dest_floor    = Elevator::initial_floor;


// ----------------------------------------------------------------------------
// Initial state definition
//
FSM_INITIAL_STATE(Elevator, Idle)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值