如何获取boost::statechart异步状态机当前状态?是否有类state_cast方法
Boost Statechart异步状态机的状态查询与状态变更等待实现
我按照Boost Statechart教程实现了一个异步状态机,但遇到了状态查询的问题——同步状态机有state_cast方法,异步版本没有类似接口,想知道怎么获取状态机的当前状态,或者等待状态变更。
我的异步状态机代码
#include <boost/statechart/event.hpp> #include <boost/statechart/state.hpp> #include <boost/statechart/asynchronous_state_machine.hpp> #include <boost/thread.hpp> namespace sc = boost::statechart; struct Start; struct MyMachine : sc::asynchronous_state_machine<MyMachine, Start> { MyMachine (my_context ctx) : my_base(ctx) { } }; struct Start : sc::state<Start,MyMachine> { using my_base::my_base; // 此处已实现react方法 }; struct StartEvent: boost::statechart::event<StartEvent> { }; struct MyCustomEvent: boost::statechart::event<MyCustomEvent> { }; struct StopEvent: boost::statechart::event<StopEvent> { };
main.cpp代码
int main() { sc::fifo_scheduler<> scheduler( true ); // 每个状态机由独立调度器处理 sc::fifo_scheduler<>::processor_handle machineHandle = scheduler.create_processor< MyMachine >(); scheduler.initiate_processor( machineHandle ); // 启动初始事件 boost::intrusive_ptr<StartEvent> startEventPtr = new StartEvent(); scheduler.queue_event(machineHandle, startEventPtr ); // 在新线程运行调度器 boost::thread threadProcessor( boost::bind( &sc::fifo_scheduler<>::operator(), &scheduler, 0 ) ); boost::intrusive_ptr<MyCustomEvent> customEventPtr = new MyCustomEvent(); scheduler.queue_event(machineHandle, customEventPtr ); // 此处需要获取MyMachine的实际状态,或等待状态变更 return 0; }
核心问题
同步状态机boost::statechart::state_machine有state_cast方法可以查询当前状态,但异步版本asynchronous_state_machine没有类似接口,请问如何实现获取当前状态或等待状态变更的功能?
解决方案
1. 扩展状态机类,添加线程安全的状态跟踪机制
在状态机内部维护当前状态的标识,同时提供查询和等待状态变更的线程安全接口:
#include <boost/statechart/event.hpp> #include <boost/statechart/state.hpp> #include <boost/statechart/asynchronous_state_machine.hpp> #include <boost/thread.hpp> #include <mutex> #include <condition_variable> namespace sc = boost::statechart; // 定义状态枚举,覆盖所有可能的状态 enum class MachineState { Start, // 添加其他状态... }; struct Start; struct MyMachine : sc::asynchronous_state_machine<MyMachine, Start> { MyMachine (my_context ctx) : my_base(ctx), currentState(MachineState::Start) { } // 查询当前状态(线程安全) MachineState GetCurrentState() const { std::lock_guard<std::mutex> lock(stateMutex); return currentState; } // 更新当前状态(供状态类调用,线程安全) void UpdateState(MachineState newState) { std::lock_guard<std::mutex> lock(stateMutex); currentState = newState; stateCond.notify_all(); // 通知所有等待状态变更的线程 } // 等待状态变更到指定目标状态 void WaitForState(MachineState targetState) { std::unique_lock<std::mutex> lock(stateMutex); stateCond.wait(lock, [this, targetState](){ return currentState == targetState; }); } private: mutable std::mutex stateMutex; MachineState currentState; std::condition_variable stateCond; }; // 在状态类的entry方法中更新状态标识 struct Start : sc::state<Start,MyMachine> { using my_base::my_base; // 进入该状态时触发 void entry() override { context<MyMachine>().UpdateState(MachineState::Start); } // 实现react方法 sc::result react(const StartEvent&) { // 状态转移逻辑... return discard_event(); } }; // 其他状态类同理,在entry()中调用UpdateState更新状态
2. 实现类型化的状态查询(类似state_cast)
如果需要精确判断当前状态的类型,可以结合type_index实现类型匹配:
#include <typeindex> struct MyMachine : sc::asynchronous_state_machine<MyMachine, Start> { MyMachine (my_context ctx) : my_base(ctx), currentStateType(typeid(Start)) { } // 判断当前是否处于指定状态类型 template<typename StateType> bool IsInState() const { std::lock_guard<std::mutex> lock(stateMutex); return currentStateType == std::type_index(typeid(StateType)); } // 更新当前状态的类型标识 void UpdateStateType(const std::type_index& type) { std::lock_guard<std::mutex> lock(stateMutex); currentStateType = type; stateCond.notify_all(); } private: mutable std::mutex stateMutex; std::type_index currentStateType; std::condition_variable stateCond; }; // 状态类中更新类型标识 struct Start : sc::state<Start,MyMachine> { void entry() override { context<MyMachine>().UpdateStateType(std::type_index(typeid(Start))); } }; // 使用示例 // if (machineInstance->IsInState<Start>()) { ... }
3. 状态变更回调机制
如果只需要在状态变更时得到通知,可以添加回调接口:
struct MyMachine : sc::asynchronous_state_machine<MyMachine, Start> { using StateChangeCallback = std::function<void(MachineState)>; MyMachine (my_context ctx) : my_base(ctx) {} // 设置状态变更回调 void SetStateChangeCallback(StateChangeCallback cb) { std::lock_guard<std::mutex> lock(cbMutex); callback = std::move(cb); } // 触发状态变更回调 void OnStateChanged(MachineState newState) { std::lock_guard<std::mutex> lock(cbMutex); if (callback) { callback(newState); } } private: mutable std::mutex cbMutex; StateChangeCallback callback; }; // 状态类中触发回调 struct Start : sc::state<Start,MyMachine> { void entry() override { context<MyMachine>().OnStateChanged(MachineState::Start); } };
注意事项
- 异步状态机运行在独立线程,所有状态相关的操作必须保证线程安全,避免数据竞争。
- 不要直接在外部线程调用状态机的内部方法,优先通过调度器事件队列或线程安全接口交互。
- 状态机实例需要通过自定义方式暴露给外部(比如在构造时保存自身指针到外部存储),因为调度器的
processor_handle不直接提供实例访问。
内容的提问来源于stack exchange,提问作者loic.lopez
相关产品推荐
相关产品推荐

