小智机器人关键函数解析,Application::MainLoop() 用于持续监听事件组中的事件,并根据不同的事件触发相应的操作

以下是对 Application::MainLoop() 函数的详细解释:
源码:

// The Main Loop controls the chat state and websocket connection
// If other tasks need to access the websocket or chat state,
// they should use Schedule to call this function
void Application::MainLoop() {
    
    
    while (true) {
    
    
        auto bits = xEventGroupWaitBits(event_group_,
            SCHEDULE_EVENT | AUDIO_INPUT_READY_EVENT | AUDIO_OUTPUT_READY_EVENT,
            pdTRUE, pdFALSE, portMAX_DELAY);

        if (bits & AUDIO_INPUT_READY_EVENT) {
    
    
            InputAudio();
        }
        if (bits & AUDIO_OUTPUT_READY_EVENT) {
    
    
            OutputAudio();
        }
        if (bits & SCHEDULE_EVENT) {
    
    
            std::unique_lock<std::mutex> lock(mutex_);
            std::list<std::function<void()>> tasks = std::move(main_tasks_);
            lock.unlock();
            for (auto& task : tasks) {
    
    
                task();
            }
        }
    }
}

函数概述

Application::MainLoop()Application 类的一个成员函数,它实现了一个无限循环,用于持续监听事件组中的事件,并根据不同的事件触发相应的操作。事件组使用 FreeRTOS 的 xEventGroupWaitBits 函数来等待事件的发生。

代码逐行解释

void Application::MainLoop() {
    
    
    while (true) {
    
    
  • 开启一个无限循环,确保 MainLoop 函数持续运行,不断监听事件。
        auto bits = xEventGroupWaitBits(event_group_,
            SCHEDULE_EVENT | AUDIO_INPUT_READY_EVENT | AUDIO_OUTPUT_READY_EVENT,
            pdTRUE, pdFALSE, portMAX_DELAY);
  • xEventGroupWaitBits 是 FreeRTOS 提供的一个函数,用于等待事件组中的某些位被设置。
    • event_group_:这是一个事件组句柄,代表要等待的事件组。
    • SCHEDULE_EVENT | AUDIO_INPUT_READY_EVENT | AUDIO_OUTPUT_READY_EVENT:指定要等待的事件位,使用按位或运算符将多个事件组合在一起。
    • pdTRUE:表示当等待的事件位被设置后,将这些位清零。
    • pdFALSE:表示只要等待的事件位中有任何一个被设置,函数就会返回,而不需要所有位都被设置。
    • portMAX_DELAY:表示无限期等待,直到有事件发生。
        if (bits & AUDIO_INPUT_READY_EVENT) {
    
    
            InputAudio();
        }
  • 检查 bits 中是否设置了 AUDIO_INPUT_READY_EVENT 位。
  • 如果设置了该位,则调用 InputAudio() 函数处理音频输入。
        if (bits & AUDIO_OUTPUT_READY_EVENT) {
    
    
            OutputAudio();
        }
  • 检查 bits 中是否设置了 AUDIO_OUTPUT_READY_EVENT 位。
  • 如果设置了该位,则调用 OutputAudio() 函数处理音频输出。
        if (bits & SCHEDULE_EVENT) {
    
    
            std::unique_lock<std::mutex> lock(mutex_);
            std::list<std::function<void()>> tasks = std::move(main_tasks_);
            lock.unlock();
            for (auto& task : tasks) {
    
    
                task();
            }
        }
  • 检查 bits 中是否设置了 SCHEDULE_EVENT 位。
  • 如果设置了该位,则执行以下操作:
    1. 使用 std::unique_lock 加锁 mutex_,确保在访问 main_tasks_ 时线程安全。
    2. 使用 std::movemain_tasks_ 中的任务移动到 tasks 列表中,避免在执行任务时对 main_tasks_ 进行修改。
    3. 解锁 mutex_,允许其他线程访问 main_tasks_
    4. 遍历 tasks 列表,依次执行每个任务。

总结

Application::MainLoop() 函数通过监听事件组中的事件,根据不同的事件触发相应的操作,实现了音频输入、输出和任务调度的功能。使用互斥锁确保了在多线程环境下对任务列表的安全访问。