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/CodePatterns/Cacheable.hpp

    r1b5188 r454bc54  
    2020
    2121#include "CodePatterns/Assert.hpp"
     22
     23#include "CodePatterns/Observer/Notification.hpp"
    2224
    2325#ifndef NO_CACHING
     
    142144
    143145  public:
    144     Cacheable(Observable *_owner, boost::function<T()> _recalcMethod, std::string name);
     146    Cacheable(
     147        Observable *_owner,
     148        const boost::function<T()> _recalcMethod,
     149        const std::string &name,
     150        const Observable::channels_t &_channels = Observable::channels_t());
    145151    virtual ~Cacheable();
    146152
     
    150156    // methods implemented for base-class Observer
    151157    void update(Observable *subject);
     158    void recieveNotification(Observable *publisher, Notification_ptr notification);
    152159    void subjectKilled(Observable *subject);
    153160  private:
     
    160167    // destroyed state is not predefined, because we rarely enter that state and never leave
    161168
    162     Observable *owner;
    163     boost::function<T()> recalcMethod;
     169    const Observable * owner;
     170    const boost::function<T()> recalcMethod;
     171
     172    //!> contains list of possible channels to enlist, if empty we signOn globally
     173    const Observable::channels_t channels;
    164174
    165175    // de-activated copy constructor
     
    169179
    170180  template<typename T>
    171   Cacheable<T>::Cacheable(Observable *_owner, boost::function<T()> _recalcMethod, std::string name) :
    172     Observer(name + "(Cached)"),
     181  Cacheable<T>::Cacheable(
     182      Observable *_owner,
     183      const boost::function<T()> _recalcMethod,
     184      const std::string &_name,
     185      const Observable::channels_t &_channels) :
     186    Observer(_name + "(Cached)"),
    173187    owner(_owner),
    174     recalcMethod(_recalcMethod)
     188    recalcMethod(_recalcMethod),
     189    channels(_channels)
    175190  {
    176191    // create all states needed for this object
     
    180195    // we sign on with the best(=lowest) priority, so cached values are recalculated before
    181196    // anybody else might ask for updated values
    182     if (owner != NULL)
    183       owner->signOn(this,Observable::PriorityLevel(int(-20)));
     197    if (owner != NULL) {
     198      if (channels.empty()) {
     199        owner->signOn(this,Observable::PriorityLevel(int(-20)));
     200      } else {
     201        for (Observable::channels_t::const_iterator iter = channels.begin();
     202            iter != channels.end(); ++iter)
     203          owner->signOn(this,*iter,Observable::PriorityLevel(int(-20)));
     204      }
     205    }
    184206  }
    185207
     
    204226  Cacheable<T>::~Cacheable()
    205227  {
    206     if (owner != NULL)
    207       owner->signOff(this);
     228    if (owner != NULL) {
     229      if (channels.empty()) {
     230        owner->signOff(this);
     231      } else {
     232        for (Observable::channels_t::const_iterator iter = channels.begin();
     233            iter != channels.end(); ++iter)
     234          owner->signOff(this,*iter);
     235      }
     236    }
    208237  }
    209238
     
    215244  template<typename T>
    216245  void Cacheable<T>::update(Observable *subject) {
     246    ASSERT( channels.empty(),
     247        "Cacheable<T>::update() - we are listening only to global updates.");
    217248    state->invalidate();
     249  }
     250
     251  template<typename T>
     252  void Cacheable<T>::recieveNotification(Observable *publisher, Notification_ptr notification) {
     253    if (publisher == owner) {
     254      ASSERT( !channels.empty(),
     255          "Cacheable<T>::update() - we are not listening to global updates.");
     256      const Observable::channels_t::const_iterator iter = std::find(
     257          channels.begin(), channels.end(), notification->getChannelNo());
     258      if (iter != channels.end())
     259        state->invalidate();
     260    }
    218261  }
    219262
     
    248291    // methods implemented for base-class Observer
    249292    void update(Observable *subject);
     293    void recieveNotification(Observable *publisher, Notification_ptr notification);
    250294    void subjectKilled(Observable *subject);
    251295  private:
     
    280324
    281325  template<typename T>
     326  void Cacheable<T>::recieveNotification(Observable *publisher, Notification_ptr notification) {
     327    ASSERT(0, "Cacheable::recieveNotification should never be called when caching is disabled");
     328  }
     329
     330  template<typename T>
    282331  void Cacheable<T>::subjectKilled(Observable *subject){
    283332    ASSERT(0, "Cacheable::subjectKilled should never be called when caching is disabled");
Note: See TracChangeset for help on using the changeset viewer.