Em sistemas embarcados, a comunicação direta entre módulos de aplicação pode gerar acoplamento indesejado. Considere um dispositivo com módulos de interface homem-máquina (HMI) e comnuicação, onde a troca de dados através de chamadas diretas ou variáveis globais compromete a manutenibilidade.
Uma solução eficaz é empregar uma camada comum para implementar o padrão Observer, permitindo desacoplamento. Este padrão utiliza callbacks para notificações, onde um módulo publica eventos e outros se inscrevem para atualizações.
As vantagens incluem desacoplamento entre módulos, facilidade para adicionar ou remover observadores sem alterar o código do sujeito, e maior estabilidade do sistema. No entanto, desvantagens podem surgir, como atrasos nas notificações se callbacks forem numerosos ou lentos, além do risco de dependências circulares que levam a travamentos.
Para mitigar problemas, callbacks devem ser concisos e evitar chamadas recursivas entre observadores.
A seguir, um exemplo de implementação em C com nomes de variáveis e estruturas modificados.
Definições do Sistema de Eventos
#ifndef EVENT_DISPATCHER_H
#define EVENT_DISPATCHER_H
#include <stdint.h>
typedef enum {
MOD_INTERFACE = 0,
MOD_CONFIG,
MOD_TOTAL
} ModuleTag;
typedef enum {
EVT_CONFIG_REFRESH,
EVT_NUM
} EventTag;
typedef struct {
uint16_t reg_id;
uint32_t value;
} ConfigUpdatePayload;
typedef int (*EventHandler)(ModuleTag source, EventTag event, const void *payload, uint32_t size);
extern void InitEventDispatcher(void);
extern int RegisterHandler(ModuleTag listener, EventTag event, EventHandler handler);
extern int UnregisterHandler(ModuleTag listener, EventTag event);
extern int DispatchEvent(ModuleTag source, EventTag event, const void *payload, uint32_t size);
#endif
</stdint.h>
Implementação do Sistema de Eventos
#include "event_dispatcher.h"
#include <string.h>
static EventHandler handler_table[MOD_TOTAL][EVT_NUM];
void InitEventDispatcher(void) {
memset(handler_table, 0, sizeof(handler_table));
}
int RegisterHandler(ModuleTag listener, EventTag event, EventHandler handler) {
if (listener >= 0 && listener < MOD_TOTAL && event < EVT_NUM) {
handler_table[listener][event] = handler;
return 0;
}
return -1;
}
int UnregisterHandler(ModuleTag listener, EventTag event) {
if (listener >= 0 && listener < MOD_TOTAL && event < EVT_NUM) {
handler_table[listener][event] = NULL;
return 0;
}
return -1;
}
int DispatchEvent(ModuleTag source, EventTag event, const void *payload, uint32_t size) {
if (event < EVT_NUM) {
for (int idx = 0; idx < MOD_TOTAL; idx++) {
if (handler_table[idx][event] != NULL) {
handler_table[idx][event](source, event, payload, size);
}
}
return 0;
}
return -1;
}
</string.h>
Módulo de Gerenciamento de Configuração
#include "event_dispatcher.h"
static int ConfigEventHandler(ModuleTag source, EventTag event, const void *payload, uint32_t size);
void ConfigModuleInit(void) {
RegisterHandler(MOD_CONFIG, EVT_CONFIG_REFRESH, ConfigEventHandler);
}
int ConfigEventHandler(ModuleTag source, EventTag event, const void *payload, uint32_t size) {
if (event == EVT_CONFIG_REFRESH) {
ConfigUpdatePayload *info = (ConfigUpdatePayload *)payload;
PersistConfiguration(info->reg_id, info->value);
}
return 0;
}
Módulo de Interface
#include "event_dispatcher.h"
void InterfaceModuleInit(void) {
// Configuração inicial
}
int TriggerConfigUpdate(void) {
ConfigUpdatePayload data;
data.reg_id = 5;
data.value = 20;
return DispatchEvent(MOD_INTERFACE, EVT_CONFIG_REFRESH, &data, sizeof(ConfigUpdatePayload));
}