Дочерний объект не передается в функции update() шаблона проектирования наблюдателя

#c #embedded #freertos

Вопрос:

Я пытаюсь интегрировать шаблон наблюдателя в свое встроенное приложение на основе FreeRTOS с идеей отправки уведомлений наблюдателям на основе того, на что они подписались.

Это SysTsk::mainThread поток, который принимает вводимые пользователем данные, которые могут включать в себя «прикрепление» или «отсоединение» определенных уведомлений. Эта часть здесь не нужна, поэтому я не включил большую ее часть.

Похоже, что дизайн действительно работает, но есть проблема, когда subject указатель в void update(Subject *subject) не соответствует самому SensorA классу, а точнее Subject , и адреса не совпадают в if условии.

 //observer.hpp
class Subject;

class Observer 
{
    public:
    virtual ~Observer() = defau<
    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() = defau<
         
    Observer *observerList[observerMaxSize];
    void attach(Observer *obs);
    void detach(Observer *obs);
    void notify(Subject*);
};

// notification.hpp
class Notification : public Observer
{
    SensorA amp;_subject;
    public:
    Notification(SensorA amp;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 == amp;_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, amp;msg, 0) == pdPASS)  // user input passed via Queue from ISR {
           // parse user input
      }
   }
}
 

Комментарии:

1. Невозможно сказать, что не так, так как опубликованный код неполон и не будет компилироваться. Можете ли вы придумать короткий, автономный, компилируемый пример программы ( sscce.org ) что люди могут работать на своих собственных машинах, чтобы воспроизвести и расследовать неисправность?

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

3. Вам не нужно размещать встроенное приложение, просто напишите небольшую «игрушечную» программу, которая демонстрирует дизайн наблюдателя, который вы придумали, и проблему, с которой вы столкнулись. Скорее всего, вы поймете, в чем проблема, пока будете этим заниматься, но если нет, вы можете опубликовать это здесь, и кто-то другой, вероятно, это сделает.

4. одна вещь, которую я заметил в отладчике, — это значение _subject изменений с ожидаемого значения на неожиданное в какой -то момент, и я не могу видеть его значение в наблюдателе, если только выполнение не переходит в Notification класс, что во время конструктора нормально, и не совсем один раз Notification::update срабатывает. Вероятно, нет никакого способа сработать, как только значение изменится, а?

Ответ №1:

Это странно. Когда выполнение переходит к следующему коду, _subject кажется, что у него странный адрес

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

пока я не добавил ненужную дополнительную строку кода в начале функции

 void update(Subject *subject) {
   int random = 0;
        if (subject == amp;_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?