// // Created by misaki on 2025/9/4. // #pragma once #include #include #include #include #include #include #include #include #include /** * @brief 线程配置结构体 * * 用于配置线程的各种属性,如名称、核心绑定、栈大小和优先级 */ struct ThreadConfig { std::string name = "thread"; // 线程名称 int core_id = -1; // 绑定核心ID (-1表示不绑定) int stack_size = 3072; // 栈大小 (字节) int priority = 5; // 优先级 bool inherit_cfg = false; // 是否允许子线程继承此配置 }; /** * @brief 线程管理类 * * 封装了ESP32上的线程创建和管理功能,支持普通函数、类成员函数和单例类成员函数 */ class ThreadManager { public: /** * @brief 创建并启动一个线程 * * @tparam Function 函数类型 * @tparam Args 参数类型 * @param config 线程配置 * @param func 要执行的函数 * @param args 函数参数 * @return std::thread 创建的线程对象 */ template static std::thread createThread(const ThreadConfig& config, Function&& func, Args&&... args) { // 创建ESP32线程配置 auto esp_cfg = create_esp_config(config); // 设置线程配置 esp_pthread_set_cfg(&esp_cfg); // 创建并启动线程 return std::thread(std::forward(func), std::forward(args)...); } /** * @brief 创建并启动一个执行类成员函数的线程 * * @tparam T 类类型 * @tparam Method 成员函数类型 * @tparam Args 参数类型 * @param config 线程配置 * @param obj 类对象指针 * @param method 成员函数指针 * @param args 函数参数 * @return std::thread 创建的线程对象 */ template static std::thread createMemberThread(const ThreadConfig& config, T* obj, Method&& method, Args&&... args) { // 使用lambda表达式包装成员函数调用 auto task = [obj, method, args...]() { (obj->*method)(args...); }; // 创建ESP32线程配置 auto esp_cfg = create_esp_config(config); // 设置线程配置 esp_pthread_set_cfg(&esp_cfg); // 创建并启动线程 return std::thread(task); } /** * @brief 创建并启动一个执行单例类成员函数的线程 * * @tparam T 单例类类型 * @tparam Method 成员函数类型 * @tparam Args 参数类型 * @param config 线程配置 * @param method 成员函数指针 * @param args 函数参数 * @return std::thread 创建的线程对象 */ template static std::thread createSingletonThread(const ThreadConfig& config, Method&& method, Args&&... args) { // 获取单例实例 T* instance = T::getInstance(); // 获取单例实例,注意这里就要求每个单例都要实现这个同名的静态函数 // 使用lambda表达式包装成员函数调用 auto task = [instance, method, args...]() { (instance->*method)(args...); }; // 创建ESP32线程配置 auto esp_cfg = create_esp_config(config); // 设置线程配置 esp_pthread_set_cfg(&esp_cfg); // 创建并启动线程 return std::thread(task); } /** * @brief 打印当前线程信息 * * @param extra 额外信息 */ static void printThreadInfo(const char *extra = nullptr) { std::stringstream ss; if (extra) { ss << extra; } ss << ", 任务名: " << pcTaskGetName(nullptr) << "核心 id: " << xPortGetCoreID() << ", 优先级: " << uxTaskPriorityGet(nullptr) << ", 栈剩余空间: " << uxTaskGetStackHighWaterMark(nullptr) << " bytes."; ESP_LOGI(pcTaskGetName(nullptr), "%s", ss.str().c_str()); } /** * @brief 打印系统内存信息 */ static void print_sys_memory() { size_t internal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); size_t spiram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); printf("Internal(内部): %zu kB, SPIRAM(外部): %zu kB\n", internal / 1024, spiram / 1024); } static void stats_task() { char stats_buf[2 * 1024]; // 存储任务列表和绑核信息,占用 2KB 栈空间,调用时需注意 /* 任务列表 + 绑核信息 */ printf("\n-------- vTaskList --------\n"); vTaskList(stats_buf); printf("Name State Prio HWM Num Core\n"); printf("%s", stats_buf); /* 各任务 CPU 使用率(已按核分开统计) */ printf("-------- vTaskGetRunTimeStats --------\n"); vTaskGetRunTimeStats(stats_buf); printf("Task AbsTime %%Time\n"); printf("%s", stats_buf); } private: /** * @brief 创建ESP32线程配置 * * @param config 线程配置 * @return esp_pthread_cfg_t ESP32线程配置 */ static esp_pthread_cfg_t create_esp_config(const ThreadConfig& config) { auto cfg = esp_pthread_get_default_config(); cfg.thread_name = config.name.c_str(); cfg.pin_to_core = config.core_id; cfg.stack_size = config.stack_size; cfg.prio = config.priority; cfg.inherit_cfg = config.inherit_cfg; return cfg; } };