Ускоренные навязчивые списки должны быть изменчивыми при пересечении контекста прерывания или потока - PullRequest
0 голосов
/ 25 ноября 2018

Улучшенная навязчивая библиотека и, в частности, расширенный навязчивый список, является отличной реализацией для небольших встроенных систем, таких как процессор Cortex-M / R.

Однако при добавлении элементов в список в прерывании и проверкеих в контексте задачи или другого прерывания. Я ожидаю, что хук должен быть квалифицирован ключевым словом volatile.

  1. Является ли это на самом деле требованием?Или я что-то упустил?
  2. Как мне объявить хук как volatile и получить список для принятия параметра шаблона?Здесь мне нужна помощь, и я не могу получить шаблоны Observable::list_type и Observer::list_hook_type для согласования.

Вот мой минимальный пример кода, файл test_observer.cc.Библиотеки Boost 1.66.0 и включены в -I /opt/boost (который является символической ссылкой /opt/boost@ -> boost_1_66_0). Компилируются с:

g++ -g -Wall -Wmissing-field-initializers -Wpointer-arith -Wuninitialized -Winit-self -Wstrict-overflow -Wundef -Wshadow -std=c++17 -I . -I /opt/boost/include test_observer.cc -o test_observer

Менее минимальная реализация с Makefile находится здесь:https://github.com/natersoz/patterns/tree/master/observer/intrusive_list_member

/**
 * @file test_observer.cc
 * Test application for classes Observer and Observable.
 */

#include <boost/intrusive/list.hpp>
#include <iostream>

/** @class Observer. */
template <typename NotificationType>
class Observer
{
public:
    virtual ~Observer()                     = default;
    Observer()                              = default;
    Observer(Observer const&)               = delete;
    Observer(Observer &&)                   = delete;
    Observer& operator = (Observer const&)  = delete;
    Observer& operator=(Observer&&)         = delete;

    virtual void Notify(NotificationType const &notification) = 0;

    using list_hook_type = boost::intrusive::list_member_hook<
        boost::intrusive::link_mode<boost::intrusive::auto_unlink>
        >;

    list_hook_type hook;
};

template <typename NotificationType>
class Observable
{
public:
    ~Observable()                               = default;
    Observable()                                = default;
    Observable(Observable const&)               = delete;
    Observable(Observable&&)                    = delete;
    Observable& operator = (Observable const&)  = delete;
    Observable& operator=(Observable&&)         = delete;

    /**  Notify all observers of an event. */
    void NotifyAll(NotificationType const &notification)
    {
        for (auto observer_iter = observer_list.begin();
             observer_iter != observer_list.end();
            )
        {
            Observer<NotificationType> &observer = *observer_iter;
            ++observer_iter;
            observer.Notify(notification);
        }
    }

    using list_type =
    boost::intrusive::list<
        Observer<NotificationType>,
        boost::intrusive::constant_time_size<false>,
        boost::intrusive::member_hook<
            Observer<NotificationType>,
            typename Observer<NotificationType>::list_hook_type,
            &Observer<NotificationType>::hook>
    >;

    list_type observer_list;
};

static Observable<int> test_observable;

/**
 * @class TestObserver
 * A simple observer which gets notifications of integers.
 */
class TestObserver: public Observer<int>
{
public:
    virtual void Notify(int const &notification)
    {
        std::cout << "notified: " << notification << std::endl;
    };
};

static TestObserver test_observer_1;

int main(void)
{
    test_observable.observer_list.push_back(test_observer_1);

    test_observable.NotifyAll(1);
    test_observable.NotifyAll(2);
    test_observable.NotifyAll(3);
    test_observable.NotifyAll(4);

    return 0;
}
...