tinyfsm icon indicating copy to clipboard operation
tinyfsm copied to clipboard

How to use an event queue?

Open mo-krauti opened this issue 11 months ago • 1 comments

I have adapted the main.cpp of the elevator example to use an event queue like this:

#include "fsmlist.hpp"

#include <iostream>

#include <queue>
std::queue<tinyfsm::Event> event_queue;

int main()
{
  fsm_list::start();

  Call call;
  FloorSensor sensor;

  while(1)
  {
    char c;

    std::cout << "c=Call, f=FloorSensor, a=Alarm, q=Quit ? ";
    std::cin >> c;
    switch(c) {
    case 'c':
      std::cout << "Floor ? ";
      std::cin >> call.floor;
      event_queue.push(call);
      break;
    case 'f':
      std::cout << "Floor ? ";
      std::cin >> sensor.floor;
      event_queue.push(sensor);
      break;
    case 'a':
      event_queue.push(Alarm());
      break;
    case 'q':
      std::cout << "Thanks for playing!" << std::endl;
      return 0;
    default:
      std::cout << "Invalid input" << std::endl;
    };
    send_event(event_queue.front());
    event_queue.pop();
  }
}

Now the state machine always calls the default

  void react(tinyfsm::Event const &) {};

event handler. Probably because the events are upcasted in the queue to tinyfsm::Event?
But how am I supposed to implement event queuing instead?

Reproducing:

  • replace main.cpp with my adapted version
  • press a to trigger the alarm event

Expected output:

*** calling firefighters ***
Motor: stopped

Actual output: Nothing

mo-krauti avatar Mar 19 '25 12:03 mo-krauti

After some research I found a workaround: Define a variant with all events

using EventVariant = std::variant<
  Call,
  FloorSensor,
  ....
>;

std::queue<EventVariant> event_queue;

And use a visitor to get the event using the original event struct type:

      std::visit([](const auto& event) {
        send_event(event);
      }, event_queue.front());
      event_queue.pop();

This requires at least c++17

mo-krauti avatar Mar 20 '25 15:03 mo-krauti