From 1a832ce483ff8c1276bc3cd3d97e3caadb38c4df Mon Sep 17 00:00:00 2001 From: Romain Forlot Date: Mon, 25 Sep 2017 01:10:42 +0200 Subject: Implement recursionCheck using observer pattern Change-Id: Ic404c098f316106abe1918c3cd100ae047f4f555 Signed-off-by: Romain Forlot --- signal-composer-binding/observer-pattern.hpp | 41 ++------- .../signal-composer-binding.cpp | 6 +- signal-composer-binding/signal.cpp | 99 ++++++---------------- signal-composer-binding/signal.hpp | 9 ++ 4 files changed, 47 insertions(+), 108 deletions(-) diff --git a/signal-composer-binding/observer-pattern.hpp b/signal-composer-binding/observer-pattern.hpp index aba2847..940a80b 100644 --- a/signal-composer-binding/observer-pattern.hpp +++ b/signal-composer-binding/observer-pattern.hpp @@ -63,31 +63,11 @@ public: if(it != observableList_.end()) {observableList_.erase(it);} } -/* - void recursionCheck(T* obs) - { - for (const auto& obs: observersList_) - { - if( id_ == obs->id()) - {return -1;} - if( origId == obs->id()) - {return -1;} - if(! obs->recursionCheck(origId)) - {return -1;} - } - return 0; - } -*/ }; template class Observable { -private: - std::list*> observerList_; - typedef typename std::list*>::iterator iterator_; - typedef typename std::list*>::const_iterator const_iterator_; - public: void addObserver(Observer* observer) { @@ -101,19 +81,10 @@ public: if(it != observerList_.end()) {observerList_.erase(it);} } -/* - int recursionCheck() - { - for (auto& obs: observerList_) - { - if( static_cast(obs) == static_cast(this)) - {return -1;} - if( obs->recursionCheck(id_)) - {return -1;} - } - return 0; - } -*/ + + virtual int initialRecursionCheck() = 0; + virtual int recursionCheck(T* obs) = 0; + virtual ~Observable() { iterator_ itb = observerList_.begin(); @@ -126,6 +97,10 @@ public: } protected: + std::list*> observerList_; + typedef typename std::list*>::iterator iterator_; + typedef typename std::list*>::const_iterator const_iterator_; + void notify() { iterator_ itb=observerList_.begin(); diff --git a/signal-composer-binding/signal-composer-binding.cpp b/signal-composer-binding/signal-composer-binding.cpp index d4236a0..44b644c 100644 --- a/signal-composer-binding/signal-composer-binding.cpp +++ b/signal-composer-binding/signal-composer-binding.cpp @@ -217,16 +217,16 @@ int execConf() { sig->attachToSourceSignals(composer); } -/* + for(auto& sig: allSignals) { - if( (err += sig->recursionCheck()) ) + if( (err += sig->initialRecursionCheck()) ) { AFB_ERROR("There is an infinite recursion loop in your signals definition. Root coming from signal: %s", sig->id().c_str()); return err; } } -*/ + composer.execSignalsSubscription(); AFB_DEBUG("Signal Composer Control configuration Done.\n signals=%d", (int)sigCount); diff --git a/signal-composer-binding/signal.cpp b/signal-composer-binding/signal.cpp index 2dcc552..a74889d 100644 --- a/signal-composer-binding/signal.cpp +++ b/signal-composer-binding/signal.cpp @@ -184,52 +184,6 @@ void Signal::attachToSourceSignals(Composer& composer) } } -/// @brief Call update() method on observer Signal with -/// current Signal timestamp and value -/*void Signal::notify() const -{ - for (int i = 0; i < Observers_.size(); ++i) - Observers_[i]->update(timestamp_, value_); -} - -/// @brief Inner recursion check. Argument is the Signal id coming -/// from the original Signal that made a recursion check. -/// -/// @param[in] origId - name of the origine of the recursion check -/// -/// @return 0 if no infinite loop detected, -1 if not. -int Signal::recursionCheck(const std::string& origId) const -{ - for (const auto& obs: observersList_) - { - if( id_ == obs->id()) - {return -1;} - if( origId == obs->id()) - {return -1;} - if(! obs->recursionCheck(origId)) - {return -1;} - } - return 0; -} - -/// @brief Recursion check to ensure that there is no infinite loop -/// in the Observers/Observables structure. -/// This will check that observer signal is not the same than itself -/// then trigger the check against the following eventuals observers -/// -/// @return 0 if no infinite loop detected, -1 if not. -int Signal::recursionCheck() const -{ - for (const auto& obs: observersList_) - { - if( id_ == obs->id()) - {return -1;} - if( obs->recursionCheck(id_)) - {return -1;} - } - return 0; -}*/ - /// @brief Make an average over the last X 'seconds' /// /// @param[in] seconds - period to calculate the average @@ -339,39 +293,40 @@ struct SignalValue Signal::last() const return history_.rbegin()->second; } -/* -template -Observable::~Observable() -{ - iterator_ itb = observerList_.begin(); - const_iterator_ ite = observerList_.end(); - - for(;itb!=ite;++itb) - { - (*itb)->delObservable(this); - } -} -template -Observer::~Observer() +/// @brief Recursion check to ensure that there is no infinite loop +/// in the Observers/Observables structure. +/// This will check that observer signal is not the same than itself +/// then trigger the check against the following eventuals observers +/// +/// @return 0 if no infinite loop detected, -1 if not. +int Signal::initialRecursionCheck() { - const_iterator_ ite = observableList_.end(); - - for(iterator_ itb=observableList_.begin();itb!=ite;++itb) + for (auto& obs: observerList_) { - (*itb)->delObserver(this); + if(obs == this) + {return -1;} + if(static_cast(obs)->recursionCheck(static_cast(obs))) + {return -1;} } + return 0; } -template -void Observable::notify() +/// @brief Inner recursion check. Argument is the Signal id coming +/// from the original Signal that made a recursion check. +/// +/// @param[in] origId - name of the origine of the recursion check +/// +/// @return 0 if no infinite loop detected, -1 if not. +int Signal::recursionCheck(Signal* parentSig) { - iterator_ itb=observerList_.begin(); - const_iterator_ ite=observerList_.end(); - - for(;itb!=ite;++itb) + for (const auto& obs: observerList_) { - (*itb)->update(static_cast(this)); + Signal* obsSig = static_cast(obs); + if(parentSig->id() == static_cast(obsSig)->id()) + {return -1;} + if(! obsSig->recursionCheck(obsSig)) + {return -1;} } + return 0; } -*/ diff --git a/signal-composer-binding/signal.hpp b/signal-composer-binding/signal.hpp index 8d0d1ab..46caa23 100644 --- a/signal-composer-binding/signal.hpp +++ b/signal-composer-binding/signal.hpp @@ -40,6 +40,12 @@ struct SignalValue { std::string strVal; }; +/// @brief Holds a signal (raw or virtual) definition. Value could be of +/// different types, so an intermediate structure is use to store them. +/// A signal could also be a subject or an observer at the same time, this +/// is the behavior retained to compose virtual signals based on raw signals. +/// And this is the way that is used to update and reacts to an underlaying +/// signal change. class Signal: public Observable, public Observer { private: @@ -76,4 +82,7 @@ public: double maximum(int seconds = 0) const; struct SignalValue last() const; //int recursionCheck() const; + + int initialRecursionCheck(); + int recursionCheck(Signal* obs); }; -- cgit 1.2.3-korg