You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 21:25:56