-1

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
      }
   }
}
Jazzy
  • 324
  • 4
  • 15
  • It's impossible to say what's wrong since the code as posted is incomplete and won't compile. Can you come up with a short, self-contained, compilable example program ( http://sscce.org ) that people can run on their own machines to reproduce and investigate the fault? – Jeremy Friesner Jun 17 '21 at 04:14
  • unfortunately it's an embedded app so you won't be able to run the entire thing on an online compiler but my main concern is really on the app side that includes the observer pattern – Jazzy Jun 17 '21 at 04:19
  • You don't need to post an embedded app, just write a small "toy" program that demonstrates the observer-design you came up with and the problem you encountered. Chances are that you'll figure out what the problem is while you're doing that, but if not, you can post it here and someone else probably will. – Jeremy Friesner Jun 17 '21 at 04:37
  • one thing that I noticed in the debugger is the value of `_subject` changes from an expected value to an unexpected one at *some* point, and I can't see its value in the watcher unless the execution goes into `Notification` class, which during the constructor is fine, and not quite once `Notification::update` is triggered. There's probably no way to trigger as soon as the value changes eh? – Jazzy Jun 17 '21 at 04:53

1 Answers1

0

This is weird. When the execution gets to the following code, _subject seems to have a weird address

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
        
}

until I added some unnecessary extra line of code at the beginning of the function

void update(Subject *subject) {
   int random = 0;
        if (subject == &_subject) {    // making sure the notification is received from sensorA to process it accordingly but the address doesn't match
            random++;      
        }
   random += 5;
}


Does anyone see why would that be?
Jazzy
  • 324
  • 4
  • 15