赞
踩
TinyFSM是一个为C++设计的轻量级有限状态机开源库库。
在嵌入式系统开发中,TinyFSM等状态机适用于控制系统和通信协议等场景,然而,开发者也需考虑该库的性能并考虑是否遵循工业C++标准。
传统 C++ 实现不仅能很容易的满足工业标准的要求,还能提供更高的性能和更低的内存开销。
现代 C++ 实现虽然引入了许多新特性,可以简化代码结构,但在性能上可能不如传统 C++ 实现高效。
反而TinyFSM本身很多地方设计不满足工业C++标准。
在嵌入式系统中,传统 C++ 实现的状态机通过显式管理状态变量和使用 switch
语句处理事件,可以有效控制内存和运行时开销,同时确保代码符合 MISRA C++ 规范。以下是一个简单的门状态机示例:
#include <iostream> enum class DoorState { Closed, Open, Locked }; class DoorStateMachine { public: DoorStateMachine() : state(DoorState::Closed) {} void open() { switch (state) { case DoorState::Closed: std::cout << "Door is opened\n"; state = DoorState::Open; break; case DoorState::Open: std::cout << "Door is already open\n"; break; case DoorState::Locked: std::cout << "Cannot open, door is locked\n"; break; } } void close() { switch (state) { case DoorState::Closed: std::cout << "Door is already closed\n"; break; case DoorState::Open: std::cout << "Door is closed\n"; state = DoorState::Closed; break; case DoorState::Locked: std::cout << "Cannot close, door is locked\n"; break; } } void lock() { switch (state) { case DoorState::Closed: std::cout << "Door is locked\n"; state = DoorState::Locked; break; case DoorState::Open: std::cout << "Cannot lock, door is open\n"; break; case DoorState::Locked: std::cout << "Door is already locked\n"; break; } } private: DoorState state; }; int main() { DoorStateMachine door; door.open(); door.close(); door.lock(); door.open(); return 0; }
TinyFSM 是一个轻量级状态机库,通过继承 tinyfsm::Fsm
和定义状态类,能够直观地定义状态和事件处理函数。以下是使用 TinyFSM 实现的门状态机代码:
#include <tinyfsm.hpp> #include <iostream> struct OpenEvent : tinyfsm::Event {}; struct CloseEvent : tinyfsm::Event {}; struct LockEvent : tinyfsm::Event {}; class DoorState : public tinyfsm::Fsm<DoorState> { public: virtual void react(OpenEvent const &) { std::cout << "Invalid transition\n"; } virtual void react(CloseEvent const &) { std::cout << "Invalid transition\n"; } virtual void react(LockEvent const &) { std::cout << "Invalid transition\n"; } virtual void entry() {} virtual void exit() {} }; class Closed : public DoorState { public: void react(OpenEvent const &) override { std::cout << "Door is opened\n"; transit<Open>(); } void react(LockEvent const &) override { std::cout << "Door is locked\n"; transit<Locked>(); } }; class Open : public DoorState { public: void react(CloseEvent const &) override { std::cout << "Door is closed\n"; transit<Closed>(); } }; class Locked : public DoorState { public: void react(OpenEvent const &) override { std::cout << "Cannot open, door is locked\n"; } }; FSM_INITIAL_STATE(DoorState, Closed) int main() { DoorState::start(); DoorState::dispatch(OpenEvent()); DoorState::dispatch(CloseEvent()); DoorState::dispatch(LockEvent()); DoorState::dispatch(OpenEvent()); return 0; }
现代 C++(如 C++14 和 C++17)引入了许多新特性,使得开发高效、可维护的代码更加容易。在状态机实现中,现代 C++ 特性如 std::function
和 std::unordered_map
可以显著简化代码结构。以下是一个基于现代 C++ 实现的状态机示例:
#include <iostream> #include <functional> #include <unordered_map> enum class DoorState { Closed, Open, Locked }; enum class DoorEvent { OpenEvent, CloseEvent, LockEvent }; class DoorStateMachine { public: DoorStateMachine() : state(DoorState::Closed) { stateHandlers[DoorState::Closed][DoorEvent::OpenEvent] = [this]() { handleOpenFromClosed(); }; stateHandlers[DoorState::Closed][DoorEvent::LockEvent] = [this]() { handleLockFromClosed(); }; stateHandlers[DoorState::Open][DoorEvent::CloseEvent] = [this]() { handleCloseFromOpen(); }; stateHandlers[DoorState::Locked][DoorEvent::OpenEvent] = [this]() { handleOpenFromLocked(); }; } void handleEvent(DoorEvent event) { auto eventHandler = stateHandlers[state].find(event); if (eventHandler != stateHandlers[state].end()) { eventHandler->second(); } else { std::cout << "Invalid event\n"; } } private: void handleOpenFromClosed() { std::cout << "Door is opened\n"; state = DoorState::Open; } void handleLockFromClosed() { std::cout << "Door is locked\n"; state = DoorState::Locked; } void handleCloseFromOpen() { std::cout << "Door is closed\n"; state = DoorState::Closed; } void handleOpenFromLocked() { std::cout << "Cannot open, door is locked\n"; } DoorState state; std::unordered_map<DoorState, std::unordered_map<DoorEvent, std::function<void()>>> stateHandlers; }; int main() { DoorStateMachine door; door.handleEvent(DoorEvent::OpenEvent); door.handleEvent(DoorEvent::CloseEvent); door.handleEvent(DoorEvent::LockEvent); door.handleEvent(DoorEvent::OpenEvent); return 0; }
以下在树莓派5上测试,基本信息如下
CPU:2.4GHz 四核 64位 Arm Cortex-A76
内存:32位 LPDDR4X SDRAM,4267MT/s
使用了benchmark多次深度压测。
平均数据分别为:
TinyFSM 传统C++ 现代C++
5.91 ns 1.25 ns 413 ns
#include <benchmark/benchmark.h> #include <tinyfsm.hpp> // 事件定义 struct OpenEvent : tinyfsm::Event {}; struct CloseEvent : tinyfsm::Event {}; struct LockEvent : tinyfsm::Event {}; // 状态机基类 class DoorState : public tinyfsm::Fsm<DoorState> { public: virtual void react(OpenEvent const &) {} virtual void react(CloseEvent const &) {} virtual void react(LockEvent const &) {} virtual void entry() {} virtual void exit() {} }; // 定义具体状态类 class Closed : public DoorState { public: void react(OpenEvent const &) override { transit<Open>(); } void react(LockEvent const &) override { transit<Locked>(); } }; class Open : public DoorState { public: void react(CloseEvent const &) override { transit<Closed>(); } }; class Locked : public DoorState { public: void react(OpenEvent const &) override {} }; FSM_INITIAL_STATE(DoorState, Closed) static void BM_TinyFSM(benchmark::State &state) { for (auto _ : state) { DoorState::start(); DoorState::dispatch(OpenEvent()); DoorState::dispatch(CloseEvent()); DoorState::dispatch(LockEvent()); } } BENCHMARK(BM_TinyFSM); BENCHMARK_MAIN();
测试结果
:
Benchmark Time CPU Iterations
-----------------------------------------------------
BM_TinyFSM 5.91 ns 5.91 ns 116692670
#include <benchmark/benchmark.h> enum class DoorState { Closed, Open, Locked }; enum class DoorEvent { OpenEvent, CloseEvent, LockEvent }; class DoorStateMachine { public: DoorStateMachine() : state(DoorState::Closed) {} void handleEvent(DoorEvent event) { switch (state) { case DoorState::Closed: if (event == DoorEvent::OpenEvent) { state = DoorState::Open; } else if (event == DoorEvent::LockEvent) { state = DoorState::Locked; } break; case DoorState::Open: if (event == DoorEvent::CloseEvent) { state = DoorState::Closed; } break; case DoorState::Locked: break; } } private: DoorState state; }; static void BM_TraditionalCPPStateMachine(benchmark::State& state) { DoorStateMachine door; for (auto _ : state) { benchmark::DoNotOptimize(door); door.handleEvent(DoorEvent::OpenEvent); door.handleEvent(DoorEvent::CloseEvent); door.handleEvent(DoorEvent::LockEvent); } } BENCHMARK(BM_TraditionalCPPStateMachine); BENCHMARK_MAIN();
测试结果:
Benchmark Time CPU Iterations
-------------------------------------------------------------------
BM_TraditionalCPPStateMachine 1.25 ns 1.25 ns 558856294
#include <benchmark/benchmark.h> #include <functional> #include <unordered_map> enum class DoorState { Closed, Open, Locked }; enum class DoorEvent { OpenEvent, CloseEvent, LockEvent }; class DoorStateMachine { public: DoorStateMachine() : state(DoorState::Closed) { stateHandlers[DoorState::Closed][DoorEvent::OpenEvent] = [this]() { state = DoorState::Open; }; stateHandlers[DoorState::Closed][DoorEvent::LockEvent] = [this]() { state = DoorState::Locked; }; stateHandlers[DoorState::Open][DoorEvent::CloseEvent] = [this]() { state = DoorState::Closed; }; } void handleEvent(DoorEvent event) { auto eventHandler = stateHandlers[state].find(event); if (eventHandler != stateHandlers[state].end()) { eventHandler->second(); } } private: DoorState state; std::unordered_map<DoorState, std::unordered_map<DoorEvent, std::function<void()>>> stateHandlers; }; static void BM_ModernCPPStateMachine(benchmark::State& state) { for (auto _ : state) { DoorStateMachine door; door.handleEvent(DoorEvent::OpenEvent); door.handleEvent(DoorEvent::CloseEvent); door.handleEvent(DoorEvent::LockEvent); } } BENCHMARK(BM_ModernCPPStateMachine); BENCHMARK_MAIN();
测试结果:
Benchmark Time CPU Iterations
-------------------------------------------------------------------
BM_ModernCPPStateMachine 413 ns 413 ns 1694224
MISRA C++ 是工业领域的一个要求比较高的标准。以下是一些多态和继承的规则:
优点:
缺点:
总之,工业领域是否要选择TinyFSM还需要三思,尽管现代编程技术如 TinyFSM 对代码结构的简化带来了吸引力,但在需要遵循严格工业标准的环境中,推荐采用更传统的 C++ 编程方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。