background_task.cc 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. #include "background_task.h"
  2. #include <esp_log.h>
  3. #include <esp_task_wdt.h>
  4. #define TAG "BackgroundTask"
  5. BackgroundTask::BackgroundTask(uint32_t stack_size) {
  6. xTaskCreate([](void* arg) {
  7. BackgroundTask* task = (BackgroundTask*)arg;
  8. task->BackgroundTaskLoop();
  9. }, "background_task", stack_size, this, 2, &background_task_handle_);
  10. }
  11. BackgroundTask::~BackgroundTask() {
  12. if (background_task_handle_ != nullptr) {
  13. vTaskDelete(background_task_handle_);
  14. }
  15. }
  16. void BackgroundTask::Schedule(std::function<void()> callback) {
  17. std::lock_guard<std::mutex> lock(mutex_);
  18. if (active_tasks_ >= 30) {
  19. int free_sram = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
  20. if (free_sram < 10000) {
  21. ESP_LOGW(TAG, "active_tasks_ == %u, free_sram == %u", active_tasks_.load(), free_sram);
  22. }
  23. }
  24. active_tasks_++;
  25. main_tasks_.emplace_back([this, cb = std::move(callback)]() {
  26. cb();
  27. {
  28. std::lock_guard<std::mutex> lock(mutex_);
  29. active_tasks_--;
  30. if (main_tasks_.empty() && active_tasks_ == 0) {
  31. condition_variable_.notify_all();
  32. }
  33. }
  34. });
  35. condition_variable_.notify_all();
  36. }
  37. void BackgroundTask::WaitForCompletion() {
  38. std::unique_lock<std::mutex> lock(mutex_);
  39. condition_variable_.wait(lock, [this]() {
  40. return main_tasks_.empty() && active_tasks_ == 0;
  41. });
  42. }
  43. void BackgroundTask::BackgroundTaskLoop() {
  44. ESP_LOGI(TAG, "background_task started");
  45. while (true) {
  46. std::unique_lock<std::mutex> lock(mutex_);
  47. condition_variable_.wait(lock, [this]() { return !main_tasks_.empty(); });
  48. std::list<std::function<void()>> tasks = std::move(main_tasks_);
  49. lock.unlock();
  50. for (auto& task : tasks) {
  51. task();
  52. }
  53. }
  54. }