diff --git a/.vscode/settings.json b/.vscode/settings.json index fa393981b857a5dbcae6300ee78bf8cd29a623cb..b3baa6327cc1535e08f7028de062bb24db44cb80 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -115,7 +115,8 @@ "polynomials": "cpp", "autodiff": "cpp", "sparseextra": "cpp", - "specialfunctions": "cpp" + "specialfunctions": "cpp", + "csetjmp": "cpp" }, "cSpell.words": [ "abom", diff --git a/src/shared/events/FSM.h b/src/shared/events/FSM.h index 35a3626beabe70990d4d6978b1e096c6a55ddc28..8a9887476a419316e54baba0b73d74b172811bec 100644 --- a/src/shared/events/FSM.h +++ b/src/shared/events/FSM.h @@ -23,9 +23,13 @@ #pragma once #include <events/Event.h> +#include <events/EventBroker.h> #include <events/EventHandler.h> #include <utils/collections/SyncQueue.h> +#include <chrono> +#include <csetjmp> + #include "ActiveObject.h" namespace Boardcore @@ -51,12 +55,18 @@ public: bool testState(void (T::*testState)(const Event&)); protected: + void run() override; void handleEvent(const Event& e) override; + void waitEvent(Event events); + void waitFor(std::chrono::milliseconds time); + private: void (T::*state)(const Event&); Event specialEvent; + std::jmp_buf runLoop; + protected: // Async continuation support uint16_t asyncDelayedEventId; @@ -84,6 +94,9 @@ void FSM<T>::transition(void (T::*nextState)(const Event&)) state = nextState; specialEvent = EV_ENTRY; (static_cast<T*>(this)->*state)(specialEvent); + + // TODO: explain + longjmp(runLoop, 1); } template <class T> @@ -92,12 +105,47 @@ bool FSM<T>::testState(void (T::*testState)(const Event&)) return (this->state == testState); } +template <class T> +void FSM<T>::run() +{ + // TODO: explain + setjmp(runLoop); + + while (!shouldStop()) + { + Event e = eventList.get(); + handleEvent(e); + } +} + template <class T> void FSM<T>::handleEvent(const Event& e) { (static_cast<T*>(this)->*state)(e); } +template <class T> +void FSM<T>::waitEvent(Event event) +{ + while (!shouldStop()) + { + Event e = eventList.get(); + + if (e == event) + // The event we were waiting for has arrived + return; + + handleEvent(e); + } +} + +template <class T> +void FSM<T>::waitFor(std::chrono::milliseconds time) +{ + EventBroker::getInstance().postDelayed(EV_ASYNC_CONTINUE, 0, time.count()); + waitEvent(EV_ASYNC_CONTINUE); +} + /** * @brief Asynchronous continuation support. *