Ignore:
Timestamp:
Oct 30, 2015, 11:43:01 AM (10 years ago)
Author:
Frederik Heber <heber@…>
Children:
e24dde
Parents:
1b5188
git-author:
Frederik Heber <heber@…> (06/19/15 22:28:24)
git-committer:
Frederik Heber <heber@…> (10/30/15 11:43:01)
Message:

Added new pattern ObservedValue, contrary to Cacheable.

  • essentially updates immediately and caches a value for off-line use, safe- guard with mutexes.
  • added unit test for ObservedValue.
  • factored threeNumbers stub out of CacheableUnitTest, also used the stub in ObservedValueUnitTest.
  • we may now signOn() to Notification with a priority.
  • Cacheable can also update now via notification channels not just for global updates.
  • Observable can now also instantiate the channels directly if given a list. This was necessary as Cacheable or ObservedValue are instantiated in the constructor, too, and if listening to channels, these must already be present.
  • FIX: Channels::addChannels() used NDEBUG wrong way round.
  • ObservedValue::get() returns reference.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Observer/Notification.cpp

    r1b5188 r454bc54  
    2020#include "CodePatterns/MemDebug.hpp"
    2121
     22#include <boost/thread/locks.hpp>
     23
    2224#include "CodePatterns/Observer/Notification.hpp"
    2325#include "CodePatterns/Observer/Observer.hpp"
     
    3032Notification::~Notification(){}
    3133
    32 void Notification::addObserver(Observer *target)
     34void Notification::addObserver(Observer *target, const int priority)
    3335{
    34   targets.insert(target);
     36  boost::recursive_mutex::scoped_lock guard(TargetsLock);
     37  targets.insert( std::make_pair(priority, target) );
    3538}
    3639
    3740void Notification::removeObserver(Observer *target)
    3841{
    39   targets.erase(target);
     42  boost::recursive_mutex::scoped_lock guard(TargetsLock);
     43  for(targets_t::iterator iter=targets.begin();iter!=targets.end();) {
     44    if((*iter).second == target) {
     45      targets.erase(iter++);
     46    } else {
     47      ++iter;
     48    }
     49  }
    4050}
    4151
    4252void Notification::notifyAll(Observable * const publisher)
    4353{
    44   for(std::set<Observer*>::iterator it=targets.begin();
    45       it!=targets.end();++it){
     54  boost::recursive_mutex::scoped_lock guard(TargetsLock);
     55  // copy such that signOff() within receiving update() does not affect iterating
     56  // this is because within the same thread and with the update() signOff() may be
     57  // called and when executed it modifies targets
     58  targets_t temp_targets = targets;
     59  for(targets_t::iterator it=temp_targets.begin();
     60      it!=temp_targets.end();++it){
    4661#ifdef LOG_OBSERVER
    4762    observerLog().addMessage() << "-> Sending update from " << observerLog().getName(publisher)
    4863                               << " for channel " << channelno
    49                                << " to " << observerLog().getName(*it);
     64                               << " to " << observerLog().getName((*it).second);
    5065#endif
    51     (*it)->recieveNotification(publisher,this);
     66    (*it).second->recieveNotification(publisher,this);
    5267  }
    5368}
     
    5570void Notification::subjectKilled(Observable * const publisher)
    5671{
    57   for(std::set<Observer*>::iterator it=targets.begin();
    58       it!=targets.end();++it){
    59     (*it)->subjectKilled(publisher);
     72  boost::recursive_mutex::scoped_lock guard(TargetsLock);
     73  // copy such that signOff() within receiving subjectKilled() does not affect iterating
     74  // this is because within the same thread and with the subjectKilled() signOff() may be
     75  // called and when executed it modifies targets
     76  for(targets_t::iterator it=targets.begin();
     77      !targets.empty();it=targets.begin()){
     78    Observer *target = (*it).second;
     79    const size_t prior_size = targets.size();
     80    target->subjectKilled(publisher);
     81    if (prior_size == targets.size())
     82      targets.erase(it);
    6083  }
    6184}
Note: See TracChangeset for help on using the changeset viewer.