Найти в Дзене

👩‍💻 Шина событий на костылях

👩‍💻 Шина событий на костылях. Реализация в FreeRTOS Паттерн "шина событий" (Event Bus) - это архитектурный шаблон, который позволяет компонентам системы взаимодействовать друг с другом, обмениваясь событиями, без необходимости явного знания о существовании друг друга. Казалось бы к чему это. Начнем рассказ с архитектуры ПО, которое работает на нашем видеопроцессоре. Существует тракт обработки видео и множество модулей, которые выполняют действия в какой-то момент обработки потока кадров: 🔴перед кадром 🔴после кадра 🔴во время обработки кадра 🔴после сжатия 🔴и других событиях. Для того, что бы не нагружать центральный модуль (тракт) вызовом кучей различных функций и не менять постоянно его струтуру при изменении и добавлении функционала было решено реализовать шину событий. Основная идея в подписи задач на события и последующее их ожидание. Другие же задачи могут формировать эти события. Таким образом, даже не зная устройство друг друга, задачи взаимодействуют друг с другом и с

👩‍💻 Шина событий на костылях. Реализация в FreeRTOS

Паттерн "шина событий" (Event Bus) - это архитектурный шаблон, который позволяет компонентам системы взаимодействовать друг с другом, обмениваясь событиями, без необходимости явного знания о существовании друг друга.

Казалось бы к чему это.

Начнем рассказ с архитектуры ПО, которое работает на нашем видеопроцессоре.

Существует тракт обработки видео и множество модулей, которые выполняют действия в какой-то момент обработки потока кадров:

🔴перед кадром

🔴после кадра

🔴во время обработки кадра

🔴после сжатия

🔴и других событиях.

Для того, что бы не нагружать центральный модуль (тракт) вызовом кучей различных функций и не менять постоянно его струтуру при изменении и добавлении функционала было решено реализовать шину событий.

Основная идея в подписи задач на события и последующее их ожидание. Другие же задачи могут формировать эти события. Таким образом, даже не зная устройство друг друга, задачи взаимодействуют друг с другом и синхронизируются.

Первой попыткой реализации было использование event flags и event groups. Однако у этого подхода есть ограничения в невозможности одновременной подписки нескольких задач на одно событие. Флаг сбрасывает первая разблокированная задача.

Вторая попытка с использованием нотификаций, путь даже и с небольшим оверхедом, прижилась лучше.

Реализация заключается в использовании двухмерного массива хэндлов задач, ожидающих событий.

/// \brief Массив очередей событий

/// \note events[ количество событий ][ глубина очереди ]

static event_task_handler_t events

[ EVENT_BUS_QTY ]

[ EVENT_LIST_DEPHT ] = {0};

Подписываясь на событие задача вписывает свой хендл в свободную ячейку требуемого события, отписываюсь - стирает.

Задача которая генерирует событие посылает уведомление каждой задаче из списка.

Таким образом каждая ожидающая задача гарантированно получает уведомление и разблокируется для выполнения, заодно и решается проблема связанная со сбросом флагов в event flags.

Небольшой пример:

Источник событий

static void task_1(void * arg)

{

/* INIT TASK CODE */

for (;;){

/* CODE */

event_bus_push(EVENT_COMPETE_1);

}

}

Потребитель событий 1

static void task_2(void * arg)

{

/* INIT TASK CODE */

// Подписать текущую задачу

event_bus_subscribe(EVENT_COMPETE_1);

// Подписать задачу 3

event_bus_unsubscribe_ex(EVENT_COMPETE_1, task_3_handler);

for (;;){

if (event_bus_wait(EVENT_COMPETE_1, 100) == true){

/* CODE */

}

}

}

Потребитель событий 2

static void task_3(void * arg)

{

for (;;){

if (event_bus_wait(EVENT_COMPETE_1, 100) != true)

{

continue;

}

/* CODE */

}

}

Полный код реализации можно найти в репозитории:

https://github.com/devprodest/event-bus-freertos/tree/main

#eventbus #freertos #шинасобытий