/* * Copyright 2023 jacqueline * * SPDX-License-Identifier: GPL-3.0-only */ #pragma once #include #include #include #include #include "audio_fsm.hpp" #include "freertos/FreeRTOS.h" #include "freertos/portmacro.h" #include "freertos/queue.h" #include "system_fsm.hpp" #include "tinyfsm.hpp" #include "ui_fsm.hpp" namespace events { class Queue { public: Queue() : has_events_(xSemaphoreCreateBinary()), mut_(), events_() {} auto Add(std::function fn) { { std::lock_guard lock{mut_}; events_.push(fn); } xSemaphoreGive(has_events_); } auto Service(TickType_t max_wait) -> bool { bool res = xSemaphoreTake(has_events_, max_wait); if (!res) { return false; } bool had_work = false; for (;;) { std::function fn; { std::lock_guard lock{mut_}; if (events_.empty()) { return had_work; } had_work = true; fn = events_.front(); events_.pop(); } std::invoke(fn); } } auto has_events() -> SemaphoreHandle_t { return has_events_; } Queue(Queue const&) = delete; void operator=(Queue const&) = delete; private: SemaphoreHandle_t has_events_; std::mutex mut_; std::queue> events_; }; template class Dispatcher { public: Dispatcher(Queue* queue) : queue_(queue) {} template auto Dispatch(const Event& ev) -> void { auto dispatch_fn = [=]() { tinyfsm::FsmList::template dispatch(ev); }; queue_->Add(dispatch_fn); } auto RunOnTask(const std::function& fn) -> void { queue_->Add(fn); } Dispatcher(Dispatcher const&) = delete; void operator=(Dispatcher const&) = delete; private: Queue* queue_; }; namespace queues { auto SystemAndAudio() -> Queue*; auto Ui() -> Queue*; } // namespace queues auto System() -> Dispatcher&; auto Audio() -> Dispatcher&; auto Ui() -> Dispatcher&; } // namespace events