From 5d7cbec34cd5e473d5768b39054d99bc72ddad62 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Thu, 27 Apr 2023 12:55:30 +1000 Subject: Move DB interactions to a background thread --- src/database/db_task.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/database/db_task.cpp (limited to 'src/database/db_task.cpp') diff --git a/src/database/db_task.cpp b/src/database/db_task.cpp new file mode 100644 index 00000000..ce1cd98a --- /dev/null +++ b/src/database/db_task.cpp @@ -0,0 +1,91 @@ +#include "db_task.hpp" + +#include + +#include "esp_heap_caps.h" +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" +#include "freertos/projdefs.h" +#include "freertos/queue.h" +#include "freertos/task.h" + +namespace database { + +static const std::size_t kDbStackSize = 256 * 1024; +static StaticTask_t sDbStaticTask; +static StackType_t* sDbStack = nullptr; + +static std::atomic sTaskRunning(false); +static QueueHandle_t sWorkQueue; + +struct WorkItem { + std::function* fn; + bool quit; +}; + +auto SendToDbTask(std::function fn) -> void { + WorkItem item{ + .fn = new std::function(fn), + .quit = false, + }; + xQueueSend(sWorkQueue, &item, portMAX_DELAY); +} + +template <> +auto RunOnDbTask(std::function fn) -> std::future { + std::shared_ptr> promise = + std::make_shared>(); + SendToDbTask([=]() { + std::invoke(fn); + promise->set_value(); + }); + return promise->get_future(); +} + +void DatabaseTaskMain(void* args) { + while (true) { + WorkItem item; + if (xQueueReceive(sWorkQueue, &item, portMAX_DELAY)) { + if (item.quit) { + break; + } + if (item.fn != nullptr) { + std::invoke(*item.fn); + delete item.fn; + } + } + } + vQueueDelete(sWorkQueue); + sTaskRunning.store(false); + vTaskDelete(NULL); +} + +auto StartDbTask() -> bool { + if (sTaskRunning.exchange(true)) { + return false; + } + if (sDbStack == nullptr) { + sDbStack = reinterpret_cast( + heap_caps_malloc(kDbStackSize, MALLOC_CAP_SPIRAM)); + } + sWorkQueue = xQueueCreate(8, sizeof(std::function*)); + xTaskCreateStatic(&DatabaseTaskMain, "DB", kDbStackSize, NULL, 1, sDbStack, + &sDbStaticTask); + return true; +} + +auto QuitDbTask() -> void { + if (!sTaskRunning.load()) { + return; + } + WorkItem item{ + .fn = nullptr, + .quit = true, + }; + xQueueSend(sWorkQueue, &item, portMAX_DELAY); + while (sTaskRunning.load()) { + vTaskDelay(pdMS_TO_TICKS(1)); + } +} + +} // namespace database -- cgit v1.2.3