Skip to content

Commit

Permalink
minor improvements for the thread safe observer pattern (#1808)
Browse files Browse the repository at this point in the history
  • Loading branch information
lballabio authored Oct 20, 2023
2 parents 3a9fd60 + c7a3104 commit e5bef2e
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 14 deletions.
27 changes: 15 additions & 12 deletions ql/patterns/observable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,8 @@ namespace QuantLib {

if (ObservableSettings::instance().updatesDeferred()) {
std::lock_guard<std::mutex> sLock(ObservableSettings::instance().mutex_);
if (ObservableSettings::instance().updatesDeferred()) {
if (ObservableSettings::instance().updatesDeferred())
ObservableSettings::instance().unregisterDeferredObserver(observerProxy);
}
}

if (disconnect) {
Expand All @@ -173,18 +172,22 @@ namespace QuantLib {

void Observable::notifyObservers() {
if (ObservableSettings::instance().updatesEnabled()) {
return (*sig_)();
sig_->operator()();
}
else {
bool updatesEnabled = false;
{
std::lock_guard<std::mutex> sLock(ObservableSettings::instance().mutex_);
updatesEnabled = ObservableSettings::instance().updatesEnabled();

if (ObservableSettings::instance().updatesDeferred()) {
std::lock_guard<std::recursive_mutex> lock(mutex_);
ObservableSettings::instance().registerDeferredObservers(observers_);
}
}

std::lock_guard<std::mutex> sLock(ObservableSettings::instance().mutex_);
if (ObservableSettings::instance().updatesEnabled()) {
return (*sig_)();
}
else if (ObservableSettings::instance().updatesDeferred()) {
std::lock_guard<std::recursive_mutex> 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()();
}
}

Expand Down
12 changes: 10 additions & 2 deletions ql/patterns/observable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,9 @@ namespace QuantLib {

#else

#ifndef QL_USE_STD_SHARED_PTR
#include <boost/smart_ptr/owner_less.hpp>
#endif
#include <atomic>
#include <mutex>
#include <set>
Expand Down Expand Up @@ -401,7 +403,7 @@ namespace QuantLib {
public:
void disableUpdates(bool deferred=false) {
std::lock_guard<std::mutex> lock(mutex_);
updatesType_ = (deferred) ? UpdatesDeferred : 0;
updatesType_ = (deferred) ? UpdatesDeferred : UpdatesDisabled;
}
void enableUpdates();

Expand All @@ -410,17 +412,23 @@ namespace QuantLib {
private:
ObservableSettings() : updatesType_(UpdatesEnabled) {}

#if defined(QL_USE_STD_SHARED_PTR)
typedef std::set<ext::weak_ptr<Observer::Proxy>,
std::owner_less<ext::weak_ptr<Observer::Proxy> > >
set_type;
#else
typedef std::set<ext::weak_ptr<Observer::Proxy>,
boost::owner_less<ext::weak_ptr<Observer::Proxy> > >
set_type;
#endif

void registerDeferredObservers(const Observable::set_type& observers);
void unregisterDeferredObserver(const ext::shared_ptr<Observer::Proxy>& proxy);

set_type deferredObservers_;
mutable std::mutex mutex_;

enum UpdateType { UpdatesEnabled = 1, UpdatesDeferred = 2} ;
enum UpdateType { UpdatesDisabled = 0, UpdatesEnabled = 1, UpdatesDeferred = 2} ;
std::atomic<int> updatesType_;
};

Expand Down

0 comments on commit e5bef2e

Please sign in to comment.