Jag letade efter en trådsäker implementering av observatörsmönstret. Jag läste https://xinhuang.github.io/posts/2015-02-11-how-a-multi-threaded-implementation-of-the-observer-pattern-can-fail.html och funderade på punkt 4 ”Inte uppfinna hjulet, använd Boost.Signals2 istället” Så jag försökte följande kod och ville fråga om det är säkert att användas i en multitrådad applikation? Vad händer om en Observer
förstörs under 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(); }
Svar
Boost.Signals2 är en tråd -säkert bibliotek. Det använder mutex-låsning internt. Det finns några försiktighetsåtgärder, som förklaras i den här artikeln :
Nästan alla klasser som tillhandahålls av Boost.Signals2 är trådsäkra och kan användas i flertrådade applikationer. Exempelvis objekt av typen
boost::signals2::signal
ochboost::signals2::connection
kan nås från olika trådar.Å andra sidan är
boost::signals2::shared_connection_block
inte trådsäker. Denna begränsning är inte viktig eftersom flera objekt o f-typboost::signals2::shared_connection_block
kan skapas i olika trådar och kan använda samma anslutningsobjekt.
men i dess enklaste och standardformuläret, Boost.Signals2 är säkert för flera trådar.
Ditt givna exempel är faktiskt trådsäkert.
Vad händer om en observatör förstörs under notifyObservers?
Facket kopplas förebyggande bort.