/* * ObservedValuesContainer.hpp * * Created on: Oct 29, 2015 * Author: heber */ #ifndef OBSERVEDVALUESCONTAINER_HPP_ #define OBSERVEDVALUESCONTAINER_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "ObservedValue_types.hpp" #include #include #include #include class QtObservedInstanceBoard; /** This class contains ObservedValues of the class \b T each instance identified * by the id type \b id. * * All the reference counting is done inside this container. */ template class ObservedValuesContainer { public: //!> typedef for callback functions to be used on last SubjectKilled() typedef boost::function onDestroy_t; /** Cstor of class ObservedValuesContainer. * * \param _name name used in debugging and prints * \param _board ref to InstanceBoard * \param _onDestroy function to call when last subjectKilled() was received and * ObservedValues are destroyed */ ObservedValuesContainer( const std::string _name, QtObservedInstanceBoard &_board, const onDestroy_t _onDestroy); /** Destor of class ObservedValuesContainer. * */ ~ObservedValuesContainer(); /** Delivers the set of Observed value for the instance identified by \a _id. * * \param _id identifier of the instance * \return shared ptr to observed instance. */ typename T::ptr get(const id _id); /** Used by QtObserved.. instance to note that signOn() has been called. * * \param _id identifier of the instance who called signOn() */ void markObservedValuesAsConnected(const id _id); /** Used by QtObserved.. instance to note that signOff() has been called. * * \param _id identifier of the instance who called signOff() */ void markObservedValuesAsDisconnected(const id _id); /** Inform this container that subjectKilled() was received by one of the ObservedValues. * * \param _id identifier of the receiving instance */ void countsubjectKilled(const id _id); /** Prepares removeal a vector of observed values of an instance identified by \a _id. * * \param _id identifier of instance */ void removeObservedValues(const id _id); /** Erases a vector of observed values of an instance identified by \a _id. * * \param _id identifier of instance */ void eraseObservedValues(const id _id); private: /** \note CountedObservedValues_t needs to contain a list in the second argument * as the ObservedValuesContainer may fall behind when a single atom is created * and destroyed a number of times in a row (e.g. in the undo/redo cases). This * problem is inherent because on the one hand we keep the QtObservedAtom alive * till the last moment, i.e. till the GUI does not need it anymore where the * original instance may long have been removed from the World. On the other hand * we instantiate the e.g. QtObservedAtom as soon as the observed atom is created. */ /** Structure to contain the sequence of created observed memories. * * \note QtGUI may lag behind the creation/destruction of observed instances a * lot but one after the other must be served. Here, we keep an additional * iterator that indicates the current instance to be served. */ struct RefCountedObserved { typedef std::pair Value_t; typedef std::deque Values_t; /** Default cstor of RefCountedObservedValues. * * Make sure that currentvalue has some sensible default value. */ RefCountedObserved() : tobedestroyed(values.end()), currentvalue(values.end()) {} /** Default copy cstor of RefCountedObservedValues. * * \param _instance instance to copy */ RefCountedObserved(const RefCountedObserved & _instance) : values(_instance.values), tobedestroyed(values.begin()), currentvalue(values.begin()) {} /** Cstor of RefCountedObservedValues. * * Make sure that currentvalue has some sensible default value. * * \param _value initial value for the list */ RefCountedObserved(Value_t _value) : values(1, _value), tobedestroyed(values.begin()), currentvalue(values.begin()) {} bool empty() const { return values.empty(); } void push_back(Value_t _value) { values.push_back(_value); if (currentvalue == values.end()) currentvalue = values.end()--; if (tobedestroyed == values.end()) tobedestroyed = currentvalue; } Value_t& getCurrentValue() const { ASSERT (currentvalue != values.end(), "RefCountedObservedValues::getCurrentValue() - cannot get, no values present."); return *currentvalue; } Value_t& getEraseCandidate() const { ASSERT (tobedestroyed != values.end(), "RefCountedObservedValues::getCurrentValue() - cannot get, no values present."); return *tobedestroyed; } void eraseCurrentValue() { ASSERT (tobedestroyed != values.end(), "RefCountedObservedValues::eraseCurrentValue() - cannot erase, no values present."); if (tobedestroyed == currentvalue) ++currentvalue; values.erase(tobedestroyed); tobedestroyed = currentvalue; // removal of this instance when both iterators point to end is done inside QtObservedInstanceBoard } //!> set of values Values_t values; //!> iterator on the value that is next gonna be destroyed typename Values_t::iterator tobedestroyed; //!> iterator on the current value that is served on get typename Values_t::iterator currentvalue; }; typedef std::map CountedObservedValues_t; //!> internal vector of observed values CountedObservedValues_t ObservedValues; //!> typedef for map with subjectKilledCounts for each instance typedef std::map subjectKilledCount_t; //!> counts how many ObservedValues have already been subjectKilled() subjectKilledCount_t subjectKilledCount; //!> typedef for the set with ids to be erase typedef std::set MarkedForErase_t; //!> marks ids marked for erase (i.e. all subjectKilled() received) MarkedForErase_t MarkedForErase; //!> name used in describing the instance type const std::string NameOfType; //!> reference to InstanceBoard for callbacks on subjectKilled() QtObservedInstanceBoard &board; //!> callback function when ObservedValues need to be destroyed const onDestroy_t onDestroy; private: /** Internal function to check whether an Observed instance identified by * \a _id is still signOn() to its associated World instance. * * \param _id identifier of instance * \return true - no more signOn()s, false - else */ bool checkRefCount(const id _id) const; /** Internal function to check whether any ObservedValue identified by * \a _id is still signOn() to its associated World instance. * * \param _id identifier of instance * \return true - no more signOn()s, false - else */ bool checksubjectKilled(const id _id) const; /** Internal function to check whether the vector of ObservedValue's * identified by \a _id has been marked for erase. * * Marked for erase means that it has received all subjectKilled() * (the container not the values themselves). * * \param _id identifier of instance * \return true - marked for erase, false - else */ bool checkMarkedForErase(const id _id) const; private: //!> QtObservedInstanceBoard may access anything friend class QtObservedInstanceBoard; /** Inserts a new ObservedValue vector into the container. * * \param _id identifier of instance associated with observed values * \param _obsvalues vector of observed values of instance */ void insert(const id _id, const typename T::ptr &_obsvalues); /** Use to change the identifier associated with a vector of observed values. * * \param _oldid old identifier * \param _newid new identifier * \return true - change successful, false - else */ bool changeIdentifier(const id _oldid, const id _newid); /** Checks whether a vector of observed values of an instance identified by \a _id * is present. * * \param _id identifier of instance * \return true - present, false - else */ bool isPresent(const id _id) const; }; #endif /* OBSERVEDVALUESCONTAINER_HPP_ */