#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?