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