推荐采用ReentrantFsm类实现线程安全、可重入的有限状态机,其通过RAII保存入口状态、mutex保护、状态策略解耦及constexpr转移表提升安全性与性能。

在嵌入式系统、网络协议栈或高并发事件驱动场景中,需要一个线程安全、可被中断后重入、状态迁移逻辑清晰且不依赖全局变量的有限状态机;传统 switch-case 实现易耦合、难测试,裸指针管理易导致状态错乱,而 std::function + enum class 组合又常因捕获 this 导致隐式生命周期依赖。
定义状态枚举与事件类型
使用 scoped enum 隔离命名空间,避免隐式整型转换;事件类型必须可复制且轻量,禁止包含裸指针或文件描述符等资源句柄。
enum class State { Idle, Connecting, Transferring, Closing };
struct Event { enum Type { ConnectReq, DataReady, Timeout, DisconnectReq } type; int payload = 0; };
声明 FSM 核心接口类
FSM 接口仅暴露纯虚函数,强制派生类实现状态处理逻辑,不暴露内部状态变量或转移表。
立即学习“C++免费学习笔记(深入)”;
class FsmInterface {
public:
virtual ~FsmInterface() = default;
virtual void handle(const Event& e) = 0;
virtual State current_state() const = 0;
};
实现可重入的 FSM 主体类
采用 RAII 管理当前状态快照,每次 handle() 调用前保存入口状态,防止递归调用时状态被中途覆盖;所有状态处理函数返回 State 枚举,由基类统一执行跳转。
class ReentrantFsm : public FsmInterface {
private:
State state_ = State::Idle;
std::mutex mtx_;
State handle_idle(const Event& e);
State handle_connecting(const Event& e);
State handle_transferring(const Event& e);
State handle_closing(const Event& e);
public:
void handle(const Event& e) override {
std::lock_guard<:mutex> lk(mtx_);
auto entry_state = state_;
State next = State::Idle;
switch (state_) {
case State::Idle: next = handle_idle(e); break;
case State::Connecting: next = handle_connecting(e); break;
case State::Transferring: next = handle_transferring(e); break;
case State::Closing: next = handle_closing(e); break;
}
if (next != entry_state) state_ = next;
}
State current_state() const override { return state_; }
};
封装状态行为为独立策略对象
每个状态对应一个无状态策略类,只持有 const 引用或值语义参数,彻底消除 this 捕获风险;策略对象通过工厂函数注入,支持运行时替换。
struct IdleStrategy {
State operator()(const Event& e, State& current) const {
if (e.type == Event::ConnectReq) return State::Connecting;
return current;
}
};
struct ConnectingStrategy {
State operator()(const Event& e, State& current) const {
if (e.type == Event::Timeout) return State::Idle;
if (e.type == Event::DataReady) return State::Transferring;
return current;
}
};
策略注册方式:
std::unordered_map
strategies_[State::Idle] = IdleStrategy{};
strategies_[State::Connecting] = ConnectingStrategy{};
构建类型安全的状态转移表
使用 constexpr std::array 实现编译期查表,避免运行时 map 查找开销;表项结构体包含源状态、事件类型、目标状态、守卫条件函数指针。
struct Transition {
State from;
Event::Type event;
State to;
std::function
};
constexpr std::array transitions = {
Transition{State::Idle, Event::ConnectReq, State::Connecting},
Transition{State::Connecting, Event::DataReady, State::Transferring, [](const Event& e) { return e.payload > 0; }},
Transition{State::Connecting, Event::Timeout, State::Idle},
};
查找逻辑:
auto it = std::find_if(transitions.begin(), transitions.end(),
[this, &e](const auto& t) {
return t.from == state_ && t.event == e.type && t.guard(e);
});
if (it != transitions.end()) state_ = it->to;
注入依赖并启用现代内存管理
FSM 不持有业务对象所有权,所有依赖通过 std::shared_ptr
class NetworkFsm : public ReentrantFsm {
private:
std::shared_ptr
std::weak_ptr
public:
NetworkFsm(std::shared_ptr
std::weak_ptr
: config_(std::move(c)), conn_(std::move(conn)) {}
};
构造时传入 shared_ptr 和 weak_ptr,确保 FSM 生命周期不延长业务对象寿命;【若 conn_ 锁定失败(expired),handle() 中应立即返回而不尝试状态迁移】。


















