Подтвердить что ты не робот

Как и почему нужно использовать сигналы Boost2?

Изучение С++ и попытка познакомиться с некоторыми шаблонами. signals2 doc явно имеет множество возможностей, которые я могу делать с слотами и сигналами. Я не понимаю, какие типы приложений (варианты использования) я должен использовать для этого.

Я думаю по линиям диспетчера событий, отправляющих события. Исходя из динамически типизированного фона (С#, Java и т.д.), Вы должны использовать диспетчер событий или статический ref или обратный вызов.

Есть ли трудности в С++ с использованием межклассовых обратных вызовов? По сути, почему сигналы 2 существуют?

Один из примеров - документ/представление. Как этот шаблон лучше подходит, чем сказать, используя вектор функций и вызывая каждый из них в цикле или скажем лямбда, которая вызывает изменения состояния в зарегистрированных экземплярах класса прослушивания?

class Document
{
public:
    typedef boost::signals2::signal<void ()>  signal_t;

public:
    Document()
    {}

    /* Connect a slot to the signal which will be emitted whenever
      text is appended to the document. */
    boost::signals2::connection connect(const signal_t::slot_type &subscriber)
    {
        return m_sig.connect(subscriber);
    }

    void append(const char* s)
    {
        m_text += s;
        m_sig();
    }

    const std::string& getText() const
    {
        return m_text;
    }

private:
    signal_t    m_sig;
    std::string m_text;
};

и

class TextView
{
public:
    TextView(Document& doc): m_document(doc)
    {
        m_connection = m_document.connect(boost::bind(&TextView::refresh, this));
    }

    ~TextView()
    {
        m_connection.disconnect();
    }

    void refresh() const
    {
        std::cout << "TextView: " << m_document.getText() << std::endl;
    }
private:
    Document&               m_document;
    boost::signals2::connection  m_connection;
};
4b9b3361

Ответ 1

Boost.Signals2 - это не просто "массив обратных вызовов", он имеет много добавленной стоимости. ИМО, наиболее важные моменты:

  • Безопасность потоков: несколько потоков могут одновременно подключать/отключать/вызывать один и тот же сигнал, не вводя условия гонки. Это особенно полезно при общении с асинхронной подсистемой, такой как активный объект, запущенный в своем потоке.
  • connection и scoped_connection, которые разрешают разъединение без прямого доступа к signal. Обратите внимание, что это единственный способ отключить несравнимые слоты, например boost::function (или std::function).
  • Блокировка временных интервалов. Предоставляет чистый способ временно отключить модуль прослушивания (например, когда пользователь запрашивает приостановку приема сообщений в представлении).
  • Автоматическое отслеживание продолжительности продолжительного времени: сигнал автоматически отключается от слотов с истекшим сроком действия. Рассмотрим ситуацию, когда слот является связующим, ссылающимся на объект, не подлежащий копированию, управляемый shared_ptr s:

    shared_ptr<listener> l = listener::create();
    auto slot = bind(&listener::listen, l.get()); // we don't want aSignal_ to affect `listener` lifespan
    aSignal_.connect(your_signal_type::slot_type(slot).track(l)); // but do want to disconnect automatically when it gets destroyed
    

Конечно, можно реализовать все вышеперечисленные функциональные возможности самостоятельно "с помощью вектора функций и вызова каждого из них в цикле" и т.д., но вопрос в том, как это было бы лучше, чем Boost.Signals2. Повторное изобретательство колеса редко является хорошей идеей.