Releases
hsmcpp — Hierarchical State Machines for Embedded & Event-Driven C++
A C++ library for building scalable, maintainable hierarchical state machines for embedded and event-driven systems.
- Embedded-ready (Linux, QNX, FreeRTOS, Arduino)
- SCXML-based code generation + visual tooling
- Thread-safe, async/sync execution
- MISRA C++ checks enforced in CI
Eliminate fragile switch-case FSMs and replace them with scalable, testable state machines that work across embedded and multi-threaded systems.
Why hsmcpp for embedded systems?
- Manage complex state logic without spaghetti code
- Model behavior visually with SCXML and keep it in sync with implementation
- Debug transitions and state flow with built-in tooling
- Designed for high-performance and real-time workflows
- Integrate easily with your runtime (RTOS, Qt, STD, etc.)
Is this library a good fit for your project?
Good fit for:
- C++ engineers building event-driven and embedded systems
- Teams needing maintainable state logic at scale and architecture-as-code
May be overkill for:
- trivial FSMs
- ultra-constrained environments with no dynamic memory
Quick Start
hsmcpp supports two workflows:
- Model-driven (recommended): SCXML + code generation + visual tooling
- Code-first: define state machines directly in C++
Visual Workflow (SCXML-based)
flowchart LR
subgraph Modeling
REQ[Requirements]
SCXML[SCXML Definition]
IDE[Visual Editor]
end
subgraph Generation
GEN[Code Generator]
UML[PlantUML Diagram]
end
subgraph Runtime
HSM[C++ HSM]
DISP[Dispatcher]
APP[Application]
end
subgraph Analysis
DBG[hsmdebugger]
end
subgraph Artifacts
DESIGN[Design Documentation]
EXE[Binaries]
end
REQ --> IDE
IDE --> SCXML
SCXML --> GEN
SCXML --> UML
UML --> DESIGN
GEN --> HSM
HSM --> DISP
DISP --> APP
APP --> EXE
EXE --> DBG
DBG -. inspect / refine .-> SCXML
Minimal code-only example
#include <chrono>
#include <thread>
#include <memory>
#include <hsmcpp/hsm.hpp>
#include <hsmcpp/HsmEventDispatcherSTD.hpp>
enum class States { OFF, ON };
enum class Events { SWITCH };
int main(const int argc, const char**argv)
{
std::shared_ptr<hsmcpp::HsmEventDispatcherSTD> dispatcher = hsmcpp::HsmEventDispatcherSTD::create();
hsmcpp::HierarchicalStateMachine<States, Events> hsm(States::OFF);
// Register states
hsm.registerState(States::OFF, [&hsm](const VariantList_t& args) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
hsm.transition(Events::SWITCH);
});
hsm.registerState(States::ON, [&hsm](const VariantList_t& args) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
hsm.transition(Events::SWITCH);
});
// Register transitions
hsm.registerTransition(States::OFF, States::ON, Events::SWITCH);
hsm.registerTransition(States::ON, States::OFF, Events::SWITCH);
// Initialize HSM
hsm.initialize(dispatcher);
// Start dispatcher and block
dispatcher->join();
return 0;
}
For complete code see examples/00_helloworld/00_helloworld_std.cpp.
Minimal SCXML-based example
blink.scxml:
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="OFF">
<state id="OFF">
<invoke srcexpr="onOff"/>
<transition event="SWITCH" target="ON"/>
</state>
<state id="ON">
<invoke srcexpr="onOn"/>
<transition event="SWITCH" target="OFF"/>
</state>
</scxml>
Minimal C++ code to use the generated BlinkHsmBase:
#include "gen/BlinkHsmBase.hpp"
class BlinkHsm : public BlinkHsmBase {
protected:
void onOff(const hsmcpp::VariantVector_t&) override {
transition(BlinkHsmEvents::SWITCH);
}
void onOn(const hsmcpp::VariantVector_t&) override {
transition(BlinkHsmEvents::SWITCH);
}
};
int main(const int argc, const char** argv) {
std::shared_ptr<HsmEventDispatcherSTD> dispatcher = HsmEventDispatcherSTD::create();
BlinkHsm hsm;
if (true == hsm.initialize(dispatcher)) {
dispatcher->join();
}
return 0;
}
For complete workflows and editor integration, see Code generation docs and /examples/02_generated.
Get Started in 60 Seconds
git clone https://github.com/igor-krechetov/hsmcpp.git
cd ./hsmcpp
mkdir ./build
cd ./build
cmake ..
make -j4
# run example
./examples/00_helloworld/00_helloworld_std
Explore more examples in /examples.
Key Features
Platform support matrix
| Platform | Support | Dispatchers | Notes |
|---|---|---|---|
| Linux | ✅ | STD, GLib, GLibmm, Qt | |
| QNX | ✅ | STD | Custom dispatcher planned |
| Arduino | ✅ | Arduino | |
| FreeRTOS | ✅ | FreeRTOS | V10.3.1+ |
| Windows | ✅ | STD, Qt |
Generic
- visual state machine editors (through thirdparty editors)
- code generation based on W3C SCXML format
- PlantUML diagrams generation (from SCXML files)
- asynchronous / synchronous execution
- thread safety
- configurable event dispatchers
- visual debugger to help analyze state machine behavior
State machine related
- states
- substates (possible to define hierarchy)
- transitions
- history
- timers
- state and transition callbacks (enter, exit, state changed, on transition)
- passing data to state and transition callbacks
- parallel states
- final states
- conditional transitions
- conditional entry points
- state actions
- self transitions
- transition cancelation
- support for std::function and lambdas as callbacks
Installation
Building from source
git clone https://github.com/igor-krechetov/hsmcpp.git
cd ./hsmcpp
./srcipts/build.sh
cd ./build
make install
By default, this builds core library components, tests, and examples. You can disable unneeded components with CMake options. See Getting started page for details and more options.
Supported package managers
| Package manager | Status |
|---|---|
| PlatformIO | ✅ |
| Arduino library registry | ✅ |
| Conan | TODO |
| Ubuntu (TBD) | TODO |
Dependencies
- For library:
- C++11 or newer
- glib (optional, for dispatcher)
- glibmm (optional, for dispatcher)
- Qt (optional, for dispatcher)
- For build:
- cmake 3.16+
- Visual Studio 2015+ (for Windows build)
- For code generator:
- Python 3
- For hsmdebugger:
- Python 3
- PyYaml (pip3 install PyYaml)
- PySide6 (pip3 install PySide6)
- plantuml (minimal version: V1.2020.11)
Documentation
Documentation is available at hsmcpp.readthedocs.io.
Tooling
hsmdebugger
Read documentation for details on how to use debugger.

SCXML GUI Editors
Check out documentation to learn more about available editors.
Note: the dedicated editor hsm-ide is under active development and will be available soon.


Why should you use Statecharts?
Statecharts offer a surprising array of benefits
- It's easier to understand a statechart than many other forms of code.
- The behaviour is decoupled from the component in question.
- This makes it easier to make changes to the behaviour.
- It also makes it easier to reason about the code.
- And the behaviour can be tested independently of the component.
- The process of building a statechart causes all the states to be explored.
- Studies have shown that statechart based code has lower bug counts than traditional code.
- Statecharts lends itself to dealing with exceptional situations that might otherwise be overlooked.
- As complexity grows, statecharts scale well.
- A statechart is a great communicator: Non-developers can understand the statecharts, while QA can use a statecharts as an exploratory tool.
It's worth noting that you're already coding state machines, except that they're hidden in the code.
Why should you not use statecharts?
There are a few downsides to using statecharts that you should be aware of.
- Programmers typically need to learn something new, although the underpinnings (state machines) would be something that most programmers are familiar with.
- It's usually a very foreign way of coding, so teams might experience pushback based on how very different it is.
- There is an overhead to extracting the behaviour in that the number of lines of code might increase with smaller statecharts.
Why are they not used?
What are the main arguments against statecharts?
There are a few common arguments against statecharts in addition to the ones listed above:
- It's simply not needed.
- It goes against the grain of [insert name of technology].
- It increases the number of libraries, for web applications this means increased load time.
The benefits outlined above should make it clear that the introduction of statecharts is generally a net positive.
Notable alternatives
There is no one-for-all library, so if hsmcpp doesn't fully suit your needs you can check out one of these alternatives:
- Qt (using QStateMachine or QScxmlStateMachine)
- QP/C++
- TinyFSM
- Another Finite State Machine
- HFSM2
- arduino-fsm