sm ist eine bewusst minimale State-Machine in C: sm_run startet einen
Thread, ruft die Handler-Schleife auf (solange ein Handler true liefert)
und joined den Thread danach wieder. Ein Zustand ist ein
struct sm_state mit einer Handler-Funktion; der „nächste Zustand” wird dem
Handler als Argument übergeben. sm liefert nur das Laufzeitgerüst – das
Wissen (welche Zustände existieren, welche Übergänge erlaubt sind) liegt in
den Handlern bzw. bei rbs in den Regeln.
Der Handler ist der „Zustandskörper”. Rückgabe true = weiter laufen,
false = Maschine terminiert. Über next_state kann er den Folgezustand
durchreichen (bei rbs_sm wird die Zustandsauswahl aber von den Fakten
gesteuert).
Laufzeit: sm_run(next_state, user_data) startet einen eigenen Thread
(threading), führt die Schleife aus und joined den Thread am Ende –
blockierend für den Aufrufer.
sm deklariert zwei schwache virtuelle Hooks (api-Muster) und stellt leere
Defaults in sm.c bereit. Die Anwendung überschreibt sie mit einer starken
callback-Definition, um Ressourcen an den Thread-Lebenszyklus zu binden
(Aufbau ganz am Anfang, Aufräumen ganz am Ende des Worker-Threads):
sm_on_start/sm_on_stop sind der Ort für Speicherverwaltung und
Ausgangslage: Der Konstruktor baut die initiale Welt auf, die Slot-Handler
liefern laufenden externen Input, der Destruktor bilanziert das Ergebnis.
Zusammenarbeit mit rbs
rbs_sm (in libraries/rbs) baut auf sm: Jeder Schritt führt rbs_step
auf der Faktenbasis aus, sucht den ersten aktiven Slot-Marker
(rbs_sm_slot) und routet dessen Handler in die sm-Schleife. Der Handler
ist eine externe Faktenquelle (kein Konsumieren, siehe
rbs); Beendigung über false des Handlers bzw. fehlenden Marker.
Damit ist der FSM-Lebenszyklus der App über sm_on_start/sm_on_stop
vollständig im Thread-sm. Abhängigkeiten: threading + api
(transitiv: Thread-Erzeugung/-Joining, callback-Makros).
Build
cmake -S . -B buildcmake --build build
Einbindung: add_subdirectory(../../libraries/sm …), Header über den
Include-Pfad <sm/sm.h>.