I am trying to integrate an observer pattern into my FreeRTOS-based embedded application with an idea of sending notifications to the observers based on what they have subscribed to.
The SysTsk::mainThread
is a thread that takes user inputs, which could either include "attach" or "detach" certain notifications. That part isn't necessary here so I didn't include much of it.
Seems like the design does work but there's an issue where the subject
pointer in void update(Subject *subject)
doesn't correspond to the SensorA
class itself, and rather Subject
and the addresses don't match in the if
condition.
//observer.hpp
class Subject;
class Observer
{
public:
virtual ~Observer() = default;
virtual void update(Subject*) = 0;
};
// subject.hpp
static uint8_t constexpr observerMaxSize = 3;
class Observer;
class Subject
{
uint8_t headIdx = 0; // the max index till observers are populated in the buffer
uint8_t tailIdx = 0;
public:
virtual ~Subject() = default;
Observer *observerList[observerMaxSize];
void attach(Observer *obs);
void detach(Observer *obs);
void notify(Subject*);
};
// notification.hpp
class Notification : public Observer
{
SensorA &_subject;
public:
Notification(SensorA &sensorA);
void update(Subject *subject);
// ...
};
// subject.cpp
void Subject::notify(Subject *subject)
{
for (uint8_t idx = 0; idx < headIdx; idx++)
{
observerList[idx]->update(subject);
}
}
// sensorA.cpp
class SensorA : public Subject {
public:
void notify() {
for (uint8_t i = 0; i < observerSize; i++) {
observerList[i]->update(this);
}
};
void SensorA::readVal() { // invokes within the interrupt
process();
notify(); // Subject::notify()
}
void SensorA::mainThread(void) {
while(true) {
uint16_t data = initiateReadI2C();
}
}
// notification.cpp
class Notification : public Observer {
public:
Notification::Notification(SensorA sensorA) : _subject(sensorA) {
_subject.attach(this);
}
void update(Subject *subject) {
if (subject == &_subject) { // making sure the notification is received from sensorA to process it accordingly but the address doesn't match
}
};
// system.cpp - main thread that process user inputs
void SysTsk::mainThread(void){
while(true) {
if (xQueueReceive(sysTskQueue, &msg, 0) == pdPASS) // user input passed via Queue from ISR {
// parse user input
}
}
}