c++oding="utf-8" ?>
asyncfsm是无锁可重入状态机模板:用std::atomic存状态、std::any管上下文、compare_exchange_strong实现原子转移,支持defer_transition暂挂及typed_context安全取值,经多线程测试验证无崩溃。

在多线程或异步回调密集的C++项目中,状态机若被多个协程或回调同时触发转移,会因共享状态读写冲突导致崩溃或逻辑错乱——必须确保状态转移操作原子、上下文隔离、进入/退出动作可重入。
定义可重入FSM核心结构
声明模板类AsyncFSM,接受状态枚举类型StateT和上下文类型ContextT;内部用std::atomic
使用std::any作为上下文载体,而非裸指针或引用——【std::any支持任意类型值拷贝,且自动管理生命周期,避免悬挂指针】;上下文在每次状态转移时按需构造、移动或交换,不共享同一实例。
提供get_context() const返回const std::any&,set_context()接受右值引用,禁止隐式转换。
实现无锁状态转移协议
定义transition_to(StateT target, std::any&& ctx = {}):先调用on_exit(current_state) → 原子更新state_ → 调用on_enter(target, std::move(ctx))。
on_exit和on_enter均为虚函数,子类按需重写;它们必须是幂等的——重复调用不应改变对象语义,这是可重入的前提。
transition_to内部用compare_exchange_strong循环重试:若其他线程已抢先修改state_,则重新读取当前状态并校验是否仍满足转移条件;【失败时不抛异常也不断言,仅返回false,由调用方决定重试或降级】。
支持异步回调的状态暂挂与恢复
添加pending_transition_成员,类型为std::optional<:tuple std::any std::function>>>;当FSM处于“不可转移”状态(如正在执行耗时IO)时,调用defer_transition(target, ctx, resume_cb)将转移请求暂存。
resume_cb在IO完成回调中被调用,它检查pending_transition_是否存在,若存在则执行transition_to(std::get(...), std::move(std::get(...))),并清空pending_transition_。
defer_transition不阻塞线程,也不加锁;pending_transition_用std::atomic
基于std::any的上下文安全传递
方法一:构造时传入上下文值,FSM内部调用std::any_cast
方法二:提供typed_context
方法三:重载operator[],接受std::type_info参数,返回void*;适用于需要绕过类型擦除开销的底层模块,但【调用者必须确保类型正确,否则行为未定义】。
完整源码集成与编译验证
创建example_fsm.h:包含AsyncFSM声明、默认虚析构、标准构造函数(初始化state_为初始状态)。
创建example_fsm.cpp:实现transition_to、defer_transition、on_exit/on_enter空基类实现;导出符号供链接。
编写test_concurrent.cpp:启动4个std::thread,每个线程对同一FSM实例循环调用transition_to(STATE_A)→transition_to(STATE_B),运行10万次;用std::atomic_int计数器验证无状态撕裂。
编译命令:g++ -std=c++17 -O2 -pthread example_fsm.cpp test_concurrent.cpp -o fsm_test;运行./fsm_test无崩溃、无断言失败、输出最终状态一致即通过。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











