Etsin tarkkailumallin langattomaa toteutusta. Luin https://xinhuang.github.io/posts/2015-02-11-how-a-multi-threaded-implementation-of-the-observer-pattern-can-fail.html ja ajattelin kohtaa 4 ”Älä keksi pyörää uudelleen, käytä sen sijaan Boost.Signals2: ta” Joten kokeilin seuraavaa koodia ja halusin kysyä, onko sitä turvallista käyttää monisäikeisessä sovelluksessa? Mitä tapahtuu, jos Observer
tuhoutuu 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(); }
vastaus
Boost.Signals2 on ketju -safe-kirjasto. Se käyttää sisäisesti mutex-lukitusta. On joitain varoituksia, kuten tässä artikkelissa selitetään:
Lähes kaikki Boost.Signals2: n tarjoamat luokat ovat langattomia ja niitä voidaan käyttää monisäikeisissä sovelluksissa. Esimerkiksi objektit, joiden tyyppi on
boost::signals2::signal
jaboost::signals2::connection
-sovellusta voi käyttää eri säikeistä.Toisaalta
boost::signals2::shared_connection_block
ei ole säiettä turvallinen. Tämä rajoitus ei ole tärkeä, koska useita objekteja o f-tyyppiboost::signals2::shared_connection_block
voidaan luoda eri säikeissä ja käyttää samaa yhteysobjektia.
mutta sen yksinkertaisimmat ja oletusmuodot, Boost.Signals2 on monisäikeinen.
Annettu esimerkkisi on todellakin säikeetön.
Mitä tapahtuu, jos tarkkailija tuhoutuu noticeObserversin aikana?
Paikka irrotetaan ennakolta.