/* * ObservedValue_wCallback.hpp * * Created on: Oct 16, 2015 * Author: heber */ #ifndef OBSERVEDVALUE_WCALLBACK_HPP_ #define OBSERVEDVALUE_WCALLBACK_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "CodePatterns/Assert.hpp" #include "CodePatterns/ObservedValue.hpp" #include "CodePatterns/Observer/Observable.hpp" #include #include #include #include /** We derive from ObservedValue in order to tell owning instance about * subjectKilled() having been called. */ template class ObservedValue_wCallback : public ObservedValue { public: ObservedValue_wCallback( const Observable * const _owner, const boost::function &_recalcMethod, const std::string &_name, const T &_initialvalue, const Observable::channels_t &_channels, const boost::function &_callback, const boost::function &_getId) : ObservedValue(_owner, _recalcMethod, _name, _initialvalue, _channels), signedOnChannels(std::max((size_t)1,_channels.size())), callback(_callback), CallbackIsGone(false), getId(_getId) {} virtual ~ObservedValue_wCallback() {} /** Function is called by callback owner to inform about its destruction. * * \note callback must not be used after this */ void noteCallBackIsGone() { CallbackIsGone = true; } protected: virtual void subjectKilled(Observable *publisher) { ASSERT(signedOnChannels > 0, "ObservedValue_wCallback::subjectKilled() - signedOnChannels is already zero."); if ((--signedOnChannels) == 0) { ObservedValue::subjectKilled(publisher); if (!CallbackIsGone) callback(getId()); } } private: //!> if we are signOn() to multiple channels, count down before callback size_t signedOnChannels; //!> callback function to tell other entity about subjectKilled const boost::function callback; //!> is callback still alive or not bool CallbackIsGone; //!> callback function to get id const boost::function getId; }; /** Specialization of ObservedValue_wCallback for the index ObservedValue. * * The index serves as the unique identifier for the object instance whose * properties are monitored in ObservedValue. Hence, how to give a subjectKilled() * with an external getId() function? For the index the ObservedValue::get() is * the getId() we need to call! Hence, we may simply connect these internally * in this partial template specialization. * * Because atomicNumber_t, atomId_t and moleculeId_t are not unique types but * -- at the writing of this class -- just typedefs, we have to resort to the * trick with two constructors, one taking an external getId(), the other * routing the getId() internally by binding to ObservedValue::get(). */ template class ObservedValue_wCallback : public ObservedValue { public: ObservedValue_wCallback( const Observable * const _owner, const boost::function &_recalcMethod, const std::string &_name, const T &_initialvalue, const Observable::channels_t &_channels, const boost::function &_callback, const boost::function &_getId) : ObservedValue(_owner, _recalcMethod, _name, _initialvalue, _channels), signedOnChannels(std::max((size_t)1,_channels.size())), callback(_callback), CallbackIsGone(false), getId(_getId) {} ObservedValue_wCallback( const Observable * const _owner, const boost::function &_recalcMethod, const std::string &_name, const T &_initialvalue, const Observable::channels_t &_channels, const boost::function &_callback) : ObservedValue(_owner, _recalcMethod, _name, _initialvalue, _channels), signedOnChannels(std::max((size_t)1,_channels.size())), callback(_callback), CallbackIsGone(false), getId(boost::bind(&ObservedValue::get, this)) {} virtual ~ObservedValue_wCallback() {} /** Function is called by callback owner to inform about its destruction. * * \note callback must not be used after this */ void noteCallBackIsGone() { CallbackIsGone = true; } protected: virtual void subjectKilled(Observable *publisher) { ObservedValue::subjectKilled(publisher); ASSERT(signedOnChannels > 0, "ObservedValue_wCallback::subjectKilled() - signedOnChannels is already zero."); if ((--signedOnChannels) == 0) ObservedValue::subjectKilled(publisher); if (!CallbackIsGone) callback(getId()); } private: //!> if we are signOn() to multiple channels, count down before callback size_t signedOnChannels; //!> callback function to tell other entity about subjectKilled const boost::function callback; //!> is callback still alive or not bool CallbackIsGone; //!> callback function to get id const boost::function getId; }; #endif /* OBSERVEDVALUE_WCALLBACK_HPP_ */