| 1 | /*
 | 
|---|
| 2 |  * ObservedValue_wCallback.hpp
 | 
|---|
| 3 |  *
 | 
|---|
| 4 |  *  Created on: Oct 16, 2015
 | 
|---|
| 5 |  *      Author: heber
 | 
|---|
| 6 |  */
 | 
|---|
| 7 | 
 | 
|---|
| 8 | 
 | 
|---|
| 9 | #ifndef OBSERVEDVALUE_WCALLBACK_HPP_
 | 
|---|
| 10 | #define OBSERVEDVALUE_WCALLBACK_HPP_
 | 
|---|
| 11 | 
 | 
|---|
| 12 | // include config.h
 | 
|---|
| 13 | #ifdef HAVE_CONFIG_H
 | 
|---|
| 14 | #include <config.h>
 | 
|---|
| 15 | #endif
 | 
|---|
| 16 | 
 | 
|---|
| 17 | #include "CodePatterns/Assert.hpp"
 | 
|---|
| 18 | #include "CodePatterns/ObservedValue.hpp"
 | 
|---|
| 19 | #include "CodePatterns/Observer/Observable.hpp"
 | 
|---|
| 20 | 
 | 
|---|
| 21 | #include <algorithm>
 | 
|---|
| 22 | #include <string>
 | 
|---|
| 23 | 
 | 
|---|
| 24 | #include <boost/bind.hpp>
 | 
|---|
| 25 | #include <boost/function.hpp>
 | 
|---|
| 26 | 
 | 
|---|
| 27 | /** We derive from ObservedValue in order to tell owning instance about
 | 
|---|
| 28 |  * subjectKilled() having been called.
 | 
|---|
| 29 |  */
 | 
|---|
| 30 | template <class T, class id=T>
 | 
|---|
| 31 | class ObservedValue_wCallback : public ObservedValue<T>
 | 
|---|
| 32 | {
 | 
|---|
| 33 | public:
 | 
|---|
| 34 |   ObservedValue_wCallback(
 | 
|---|
| 35 |       const Observable * const _owner,
 | 
|---|
| 36 |       const boost::function<T()> &_recalcMethod,
 | 
|---|
| 37 |       const std::string &_name,
 | 
|---|
| 38 |       const T &_initialvalue,
 | 
|---|
| 39 |       const Observable::channels_t &_channels,
 | 
|---|
| 40 |       const boost::function<void()> &_callback) :
 | 
|---|
| 41 |         ObservedValue<T>(_owner, _recalcMethod, _name, _initialvalue, _channels),
 | 
|---|
| 42 |         signedOnChannels(std::max((size_t)1,_channels.size())),
 | 
|---|
| 43 |         callback(_callback),
 | 
|---|
| 44 |         CallbackIsGone(false)
 | 
|---|
| 45 |   {}
 | 
|---|
| 46 |   virtual ~ObservedValue_wCallback()
 | 
|---|
| 47 |   {}
 | 
|---|
| 48 | 
 | 
|---|
| 49 |   /** Function is called by callback owner to inform about its destruction.
 | 
|---|
| 50 |    *
 | 
|---|
| 51 |    * \note callback must not be used after this
 | 
|---|
| 52 |    */
 | 
|---|
| 53 |   void noteCallBackIsGone()
 | 
|---|
| 54 |   { CallbackIsGone = true; }
 | 
|---|
| 55 | 
 | 
|---|
| 56 | protected:
 | 
|---|
| 57 |   virtual void subjectKilled(Observable *publisher)
 | 
|---|
| 58 |   {
 | 
|---|
| 59 |     ASSERT(signedOnChannels > 0,
 | 
|---|
| 60 |         "ObservedValue_wCallback::subjectKilled() - signedOnChannels is already zero.");
 | 
|---|
| 61 |     if ((--signedOnChannels) == 0) {
 | 
|---|
| 62 |       ObservedValue<T>::subjectKilled(publisher);
 | 
|---|
| 63 |       if (!CallbackIsGone)
 | 
|---|
| 64 |         callback();
 | 
|---|
| 65 |     }
 | 
|---|
| 66 |   }
 | 
|---|
| 67 | 
 | 
|---|
| 68 | private:
 | 
|---|
| 69 |   //!> if we are signOn() to multiple channels, count down before callback
 | 
|---|
| 70 |   size_t signedOnChannels;
 | 
|---|
| 71 |   //!> callback function to tell other entity about subjectKilled
 | 
|---|
| 72 |   const boost::function<void()> callback;
 | 
|---|
| 73 |   //!> is callback still alive or not
 | 
|---|
| 74 |   bool CallbackIsGone;
 | 
|---|
| 75 | };
 | 
|---|
| 76 | 
 | 
|---|
| 77 | #endif /* OBSERVEDVALUE_WCALLBACK_HPP_ */
 | 
|---|