Căutam o implementare sigură a firului modelului de observator. Am citit https://xinhuang.github.io/posts/2015-02-11-how-a-multi-threaded-implementation-of-the-observer-pattern-can-fail.html și mă gândeam la punctul 4 „Nu” reinventați roata, folosiți în schimb Boost.Signals2 ” . Așadar, am încercat următorul cod și am vrut să întreb dacă este sigur să fie utilizat într-o aplicație cu mai multe fire? Ce se întâmplă dacă un Observer este distrus în timpul notifyObservers?
#include <boost/signals2.hpp> #include <iostream> #include <string> class AbstractObserver { public: using SignalType = boost::signals2::signal<void()>; virtual ~AbstractObserver() = default; virtual void notify() = 0; void registerAtSubject(SignalType &sig) { connection_ = sig.connect([this]() { notify(); }); } private: boost::signals2::scoped_connection connection_; }; class Subject { AbstractObserver::SignalType sig_; public: void registerObserver(AbstractObserver &observer) { observer.registerAtSubject(sig_); } void notifyObservers() const { sig_(); } }; class Observer : public AbstractObserver { std::string id_; public: explicit Observer(std::string id) : id_(std::move(id)) {}; void notify() override { std::cout << "Observer " << id_ << " got notified" << std::endl; } }; int main() { Subject c; { Observer o2("B"); { Observer o1("A"); c.registerObserver(o1); c.notifyObservers(); c.registerObserver(o2); c.notifyObservers(); } c.notifyObservers(); } c.notifyObservers(); }
Răspuns
Boost.Signals2 este un fir -bibliotecă sigură. Utilizează blocarea mutex intern. Există câteva avertismente, după cum se explică în acest articol :
Aproape toate clasele furnizate de Boost.Signals2 sunt sigure pentru fire și pot fi utilizate în aplicații cu mai multe fire. De exemplu, obiecte de tip
boost::signals2::signalșiboost::signals2::connectionpoate fi accesat din fire diferite.Pe de altă parte,
boost::signals2::shared_connection_blocknu este sigur pentru fire. Această limitare nu este importantă, deoarece mai multe obiecte o f typeboost::signals2::shared_connection_blockpoate fi creat în fire diferite și poate utiliza același obiect de conexiune.
formularele cele mai simple și implicite, Boost.Signals2 este sigur pentru mai multe fire.
Exemplul dat este, într-adevăr, sigur pentru fire.
Ce se întâmplă dacă un Observator este distrus în timpul notificationObservers?
Slotul este deconectat preventiv.