以下是对 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
位。 - 如果设置了该位,则执行以下操作:
- 使用
std::unique_lock
加锁mutex_
,确保在访问main_tasks_
时线程安全。 - 使用
std::move
将main_tasks_
中的任务移动到tasks
列表中,避免在执行任务时对main_tasks_
进行修改。 - 解锁
mutex_
,允许其他线程访问main_tasks_
。 - 遍历
tasks
列表,依次执行每个任务。
- 使用
总结
Application::MainLoop()
函数通过监听事件组中的事件,根据不同的事件触发相应的操作,实现了音频输入、输出和任务调度的功能。使用互斥锁确保了在多线程环境下对任务列表的安全访问。