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::connection
poate fi accesat din fire diferite.Pe de altă parte,
boost::signals2::shared_connection_block
nu este sigur pentru fire. Această limitare nu este importantă, deoarece mai multe obiecte o f typeboost::signals2::shared_connection_block
poate 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.