FSM 库不提供 UML“执行活动”实现

问题描述 投票:0回答:1

我在 GitHub 上寻找状态机(FSM、HSM ...)C++ 库(Boost、tinyFSM ...),我注意到它们都没有在状态内提供 UML“执行活动”。它们仅在由事件触发时在转换期间提供单个操作 (

fsm.process_event(Event{})
)。我所说的活动是指“长时间操作”(例如在线程内完成,但在事件发生时可以取消,请参阅https://cs.emis.de/LNI/Proceedings/Proceedings07/TowardEfficCode_3.pdf以获取更多参考)。我不需要真正的 std::thread,而是需要从我的状态类并发调用一个
tick()
方法(又名
on_running()
)。

伪代码总结我的想法:

struct State1 { void on_running() { ... blocking code but quick reactive } };
FSM fsm; // + init of transition table

void threaded_rountine()
{
  fsm.process_event(Event1{});
}

int main()
{
  fsm.process_event(Event2{});
  while (true)
  {
    fsm.tick(); // will call fsm.current_state.on_running() in which I can call eventually call fsm.process_event(Event3{});
  }
}

为什么,我要求这个?因为我想集成一个提供

.tick()
更新方法的库。

注意:在 UML 中,如果状态正在转换到自身,它不会调用

on_entering
on_leaving actions
(由 boost 中的构造函数/析构函数实现),因此我不确定,即在 Boost 中,如果我添加一个转换对于相同源/目标状态的操作,我可以模仿
on_running
方法)。

Boost状态图:

Do activity

- Not supported in Boost.Statechart
- A do activity can be simulated with a separate thread that is started in the entry action and cancelled (!) in the exit action of a particular state

目前,我尝试了https://www.itemis.com/en/products/itemis-create/documentation/user-guide/overview_what_are_state_machines,它允许活动,但这是一个专有工具。

所以我的问题是:

  • 有人知道提供活动的 C/C++ 库。
  • 知道为什么主要状态机库只提供事件后转换的单一操作。
  • 有同样经历并成功解决。
  • 有一个基本的例子可以提供。

提前致谢。

c++ boost fsm statechart
1个回答
0
投票

FSM 通常不提供开箱即用的功能,这并不奇怪。 执行状态模型响应性,因此它们的活动不能在管理状态模型状态的主线程上运行(或者必须在单线程系统上可中断)。此示例展示了如何使用多线程来做到这一点。

演示:https://onlinegdb.com/f0P4557kd

#include <chrono>
#include <future>
#include <mutex>
#include <condition_variable>
#include <iostream>

using namespace std::chrono_literals;

class fsm_t
{
public:
    void on_enter_doing_state()
    {
        start_activity();
    }

    void on_exit_doing_state()
    {
        cancel_activity();
    }


private:
    void start_activity()
    {
        m_activity_future = std::async(std::launch::async,[this]{ do_activity(); });
    }

    void cancel_activity()
    {
        {
            std::unique_lock lock{m_mtx};
            m_cancelled = true;
            m_cv.notify_all();
        }

        // wait for activity to finish (cancelled)
        m_activity_future.get();
    }


    void do_activity()
    {
        for(std::size_t n = 0; n < 50; ++n)
        {
            std::unique_lock lock{m_mtx};

            // simulate doing some work for 100ms and then check cancellation
            m_cv.wait_for(lock,100ms, [&]{ return m_cancelled; });
            
            //co-operative cancellation of activity!
            if(m_cancelled) 
            {
                std::cout << "\ncancelled\n";
                return;
            }
            std::cout << (n%10);
        }

        // send activity finished event to fsm.
        // send_event(event::done);
    }

    std::future<void> m_activity_future;
    bool m_cancelled{false};
    std::mutex m_mtx;
    std::condition_variable m_cv;
};

int main()
{
    fsm_t fsm;
    fsm.on_enter_doing_state();
    std::this_thread::sleep_for(2s);
    fsm.on_exit_doing_state(); // will cancel, activity not finished yet (full activity will take 5s)
}
© www.soinside.com 2019 - 2024. All rights reserved.