#include "background_task.h" #include #define TAG "BackgroundTask" BackgroundTask::BackgroundTask(uint32_t stack_size) { #if CONFIG_IDF_TARGET_ESP32S3 task_stack_ = (StackType_t*)heap_caps_malloc(stack_size, MALLOC_CAP_SPIRAM); background_task_handle_ = xTaskCreateStatic([](void* arg) { BackgroundTask* task = (BackgroundTask*)arg; task->BackgroundTaskLoop(); }, "background_task", stack_size, this, 1, task_stack_, &task_buffer_); #else xTaskCreate([](void* arg) { BackgroundTask* task = (BackgroundTask*)arg; task->BackgroundTaskLoop(); }, "background_task", stack_size, this, 1, &background_task_handle_); #endif } BackgroundTask::~BackgroundTask() { if (background_task_handle_ != nullptr) { vTaskDelete(background_task_handle_); } } void BackgroundTask::Schedule(std::function callback) { std::lock_guard lock(mutex_); if (active_tasks_ >= 30) { ESP_LOGW(TAG, "active_tasks_ == %u", active_tasks_.load()); } active_tasks_++; auto wrapped_callback = [this, callback]() { callback(); active_tasks_--; condition_variable_.notify_all(); }; main_tasks_.push_back(wrapped_callback); condition_variable_.notify_all(); } void BackgroundTask::WaitForCompletion() { std::unique_lock lock(mutex_); condition_variable_.wait(lock, [this]() { return main_tasks_.empty() && active_tasks_ == 0; }); } void BackgroundTask::BackgroundTaskLoop() { ESP_LOGI(TAG, "background_task started"); while (true) { std::unique_lock lock(mutex_); condition_variable_.wait(lock, [this]() { return !main_tasks_.empty(); }); std::list> tasks = std::move(main_tasks_); lock.unlock(); for (auto& task : tasks) { task(); } } }