diff options
author | Romain Forlot <romain.forlot@iot.bzh> | 2017-09-25 18:19:19 +0200 |
---|---|---|
committer | Romain Forlot <romain.forlot@iot.bzh> | 2017-12-14 11:00:25 +0100 |
commit | c80c2b1919a0b5cc8c67a3fcd257e965da465315 (patch) | |
tree | 95da74779e321f034e42ce83e69ab0f7e5b34b82 | |
parent | 1a832ce483ff8c1276bc3cd3d97e3caadb38c4df (diff) |
Make observer pattern thread safe
Protect list using mutex
Change way to browse lists using range-based for-loop
Change-Id: I3b94269c534e5b2ec6b60828f0283f56bab137ca
Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
-rw-r--r-- | signal-composer-binding/observer-pattern.hpp | 47 |
1 files changed, 26 insertions, 21 deletions
diff --git a/signal-composer-binding/observer-pattern.hpp b/signal-composer-binding/observer-pattern.hpp index 940a80b..d3e478b 100644 --- a/signal-composer-binding/observer-pattern.hpp +++ b/signal-composer-binding/observer-pattern.hpp @@ -18,9 +18,9 @@ /* This is a classic observer design pattern a bit enhanced to be able to pull and push info in 2 ways */ - - #include <list> - #include <algorithm> +#include <list> +#include <mutex> +#include <algorithm> template<class T> class Observable; @@ -28,14 +28,16 @@ class Observable; template<class T> class Observer { +private: + std::mutex observableListMutex_; + protected: virtual ~Observer() { - const_iterator_ ite = observableList_.end(); - - for(iterator_ itb=observableList_.begin();itb!=ite;++itb) + std::lock_guard<std::mutex> lock(observableListMutex_); + for(const auto& sig: observableList_) { - (*itb)->delObserver(this); + sig->delObserver(this); } } @@ -48,6 +50,7 @@ public: void addObservable(Observable<T>* observable) { + std::lock_guard<std::mutex> lock(observableListMutex_); for (auto& obs : observableList_) { if (obs == observable) @@ -59,8 +62,9 @@ public: void delObservable(Observable<T>* observable) { - const_iterator_ it = std::find(observableList_.begin(), observableList_.end(), observable); - if(it != observableList_.end()) + std::lock_guard<std::mutex> lock(observableListMutex_); + const_iterator_ it = std::find(observableList_.cbegin(), observableList_.cend(), observable); + if(it != observableList_.cend()) {observableList_.erase(it);} } }; @@ -71,14 +75,16 @@ class Observable public: void addObserver(Observer<T>* observer) { + std::lock_guard<std::mutex> lock(observerListMutex_); observerList_.push_back(observer); observer->addObservable(this); } void delObserver(Observer<T>* observer) { - const_iterator_ it = find(observerList_.begin(), observerList_.end(), observer); - if(it != observerList_.end()) + std::lock_guard<std::mutex> lock(observerListMutex_); + const_iterator_ it = find(observerList_.cbegin(), observerList_.cend(), observer); + if(it != observerList_.cend()) {observerList_.erase(it);} } @@ -87,12 +93,10 @@ public: virtual ~Observable() { - iterator_ itb = observerList_.begin(); - const_iterator_ ite = observerList_.end(); - - for(;itb!=ite;++itb) + std::lock_guard<std::mutex> lock(observerListMutex_); + for(const auto& obs: observerList_) { - (*itb)->delObservable(this); + obs->delObservable(this); } } @@ -103,12 +107,13 @@ protected: void notify() { - iterator_ itb=observerList_.begin(); - const_iterator_ ite=observerList_.end(); - - for(;itb!=ite;++itb) + std::lock_guard<std::mutex> lock(observerListMutex_); + for(const auto& obs: observerList_) { - (*itb)->update(static_cast<T*>(this)); + obs->update(static_cast<T*>(this)); } } + +private: + std::mutex observerListMutex_; }; |