我在 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,它允许活动,但这是一个专有工具。
所以我的问题是:
提前致谢。
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)
}