parent
fbe047a35f
commit
5d7cbec34c
@ -0,0 +1,91 @@ |
||||
#include "db_task.hpp" |
||||
|
||||
#include <functional> |
||||
|
||||
#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<bool> sTaskRunning(false); |
||||
static QueueHandle_t sWorkQueue; |
||||
|
||||
struct WorkItem { |
||||
std::function<void(void)>* fn; |
||||
bool quit; |
||||
}; |
||||
|
||||
auto SendToDbTask(std::function<void(void)> fn) -> void { |
||||
WorkItem item{ |
||||
.fn = new std::function<void(void)>(fn), |
||||
.quit = false, |
||||
}; |
||||
xQueueSend(sWorkQueue, &item, portMAX_DELAY); |
||||
} |
||||
|
||||
template <> |
||||
auto RunOnDbTask(std::function<void(void)> fn) -> std::future<void> { |
||||
std::shared_ptr<std::promise<void>> promise = |
||||
std::make_shared<std::promise<void>>(); |
||||
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<StackType_t*>( |
||||
heap_caps_malloc(kDbStackSize, MALLOC_CAP_SPIRAM)); |
||||
} |
||||
sWorkQueue = xQueueCreate(8, sizeof(std::function<void(void)>*)); |
||||
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
|
@ -0,0 +1,25 @@ |
||||
#pragma once |
||||
|
||||
#include <functional> |
||||
#include <future> |
||||
#include <memory> |
||||
|
||||
namespace database { |
||||
|
||||
auto StartDbTask() -> bool; |
||||
auto QuitDbTask() -> void; |
||||
|
||||
auto SendToDbTask(std::function<void(void)> fn) -> void; |
||||
|
||||
template <typename T> |
||||
auto RunOnDbTask(std::function<T(void)> fn) -> std::future<T> { |
||||
std::shared_ptr<std::promise<T>> promise = |
||||
std::make_shared<std::promise<T>>(); |
||||
SendToDbTask([=]() { promise->set_value(std::invoke(fn)); }); |
||||
return promise->get_future(); |
||||
} |
||||
|
||||
template <> |
||||
auto RunOnDbTask(std::function<void(void)> fn) -> std::future<void>; |
||||
|
||||
} // namespace database
|
Loading…
Reference in new issue