From 8a39407e8c69e4d6df586d3bb73efd05d05ee3c5 Mon Sep 17 00:00:00 2001 From: klaus spanderen Date: Fri, 6 Oct 2023 21:43:44 +0200 Subject: [PATCH 1/3] avoid potential double notifications --- ql/patterns/observable.cpp | 25 +++++++++++++------------ ql/patterns/observable.hpp | 4 ++-- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/ql/patterns/observable.cpp b/ql/patterns/observable.cpp index 39a7de18100..3e5eaf5a0d6 100644 --- a/ql/patterns/observable.cpp +++ b/ql/patterns/observable.cpp @@ -161,9 +161,8 @@ namespace QuantLib { if (ObservableSettings::instance().updatesDeferred()) { std::lock_guard sLock(ObservableSettings::instance().mutex_); - if (ObservableSettings::instance().updatesDeferred()) { + if (ObservableSettings::instance().updatesDeferred()) ObservableSettings::instance().unregisterDeferredObserver(observerProxy); - } } if (disconnect) { @@ -173,18 +172,20 @@ namespace QuantLib { void Observable::notifyObservers() { if (ObservableSettings::instance().updatesEnabled()) { - return (*sig_)(); + sig_->operator()(); } + else { + bool updatesEnabled = false; + { + std::lock_guard sLock(ObservableSettings::instance().mutex_); + updatesEnabled = ObservableSettings::instance().updatesEnabled(); + + if (ObservableSettings::instance().updatesDeferred()) + ObservableSettings::instance().registerDeferredObservers(observers_); + } - std::lock_guard sLock(ObservableSettings::instance().mutex_); - if (ObservableSettings::instance().updatesEnabled()) { - return (*sig_)(); - } - else if (ObservableSettings::instance().updatesDeferred()) { - std::lock_guard lock(mutex_); - // if updates are only deferred, flag this for later notification - // these are held centrally by the settings singleton - ObservableSettings::instance().registerDeferredObservers(observers_); + if (updatesEnabled) + sig_->operator()(); } } diff --git a/ql/patterns/observable.hpp b/ql/patterns/observable.hpp index 35ead03ee70..13d7dbc7fc9 100644 --- a/ql/patterns/observable.hpp +++ b/ql/patterns/observable.hpp @@ -401,7 +401,7 @@ namespace QuantLib { public: void disableUpdates(bool deferred=false) { std::lock_guard lock(mutex_); - updatesType_ = (deferred) ? UpdatesDeferred : 0; + updatesType_ = (deferred) ? UpdatesDeferred : UpdatesDisabled; } void enableUpdates(); @@ -420,7 +420,7 @@ namespace QuantLib { set_type deferredObservers_; mutable std::mutex mutex_; - enum UpdateType { UpdatesEnabled = 1, UpdatesDeferred = 2} ; + enum UpdateType { UpdatesDisabled = 0, UpdatesEnabled = 1, UpdatesDeferred = 2} ; std::atomic updatesType_; }; From 32b0cbb41ce1cc64610c35d2c741f1a5cda1b019 Mon Sep 17 00:00:00 2001 From: klaus spanderen Date: Fri, 6 Oct 2023 21:58:51 +0200 Subject: [PATCH 2/3] secure observer list --- ql/patterns/observable.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ql/patterns/observable.cpp b/ql/patterns/observable.cpp index 3e5eaf5a0d6..996b8a05063 100644 --- a/ql/patterns/observable.cpp +++ b/ql/patterns/observable.cpp @@ -180,8 +180,10 @@ namespace QuantLib { std::lock_guard sLock(ObservableSettings::instance().mutex_); updatesEnabled = ObservableSettings::instance().updatesEnabled(); - if (ObservableSettings::instance().updatesDeferred()) + if (ObservableSettings::instance().updatesDeferred()) { + std::lock_guard lock(mutex_); ObservableSettings::instance().registerDeferredObservers(observers_); + } } if (updatesEnabled) From c7a31049ce7298aa1061ab58d42d4bb06526fa21 Mon Sep 17 00:00:00 2001 From: klaus spanderen Date: Fri, 6 Oct 2023 23:43:02 +0200 Subject: [PATCH 3/3] avoid includes --- ql/patterns/observable.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ql/patterns/observable.hpp b/ql/patterns/observable.hpp index 13d7dbc7fc9..f7536c76964 100644 --- a/ql/patterns/observable.hpp +++ b/ql/patterns/observable.hpp @@ -262,7 +262,9 @@ namespace QuantLib { #else +#ifndef QL_USE_STD_SHARED_PTR #include +#endif #include #include #include @@ -410,9 +412,15 @@ namespace QuantLib { private: ObservableSettings() : updatesType_(UpdatesEnabled) {} +#if defined(QL_USE_STD_SHARED_PTR) + typedef std::set, + std::owner_less > > + set_type; +#else typedef std::set, boost::owner_less > > set_type; +#endif void registerDeferredObservers(const Observable::set_type& observers); void unregisterDeferredObserver(const ext::shared_ptr& proxy);