跨中断或线程上下文时,Boost侵入式列表挂钩应该是易变的

时间:2018-11-25 05:18:24

标签: c++ boost intrusive-containers boost-intrusive

boost侵入式库,尤其是boost intrusive列表,是使用小型嵌入式系统(例如Cortex-M / R CPU)的出色实现。

但是,当在中断中将项目添加到列表中并在任务或其他中断的上下文中检查它们时,我希望该钩子应使用volatile关键字进行限定。

  1. 这实际上是一项要求吗?还是我想念什么?
  2. 如何将钩子声明为volatile并获取列表以接受模板参数?这是我需要帮助的地方,无法获取Observable::list_typeObserver::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;
}

0 个答案:

没有答案