/* * ObservedValuesContainer_impl.hpp * * Created on: Oct 29, 2015 * Author: heber */ #ifndef OBSERVEDVALUESCONTAINER_IMPL_HPP_ #define OBSERVEDVALUESCONTAINER_IMPL_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "ObservedValuesContainer.hpp" #include "CodePatterns/Assert.hpp" template ObservedValuesContainer::ObservedValuesContainer( const std::string _name, QtObservedInstanceBoard &_board, const onDestroy_t _onDestroy) : NameOfType(_name), board(_board), onDestroy(_onDestroy) {} template ObservedValuesContainer::~ObservedValuesContainer() { for (typename CountedObservedValues_t::iterator iter = ObservedValues.begin(); iter != ObservedValues.end(); ++iter) { ASSERT( !iter->second.empty(), "~ObservedValuesContainer() of "+NameOfType+" "+toString(iter->first) +" has an empty list in ObservedValues."); for (typename RefCountedObserved::Values_t::iterator listiter = iter->second.values.begin(); listiter != iter->second.values.end(); ++listiter) { listiter->first->noteBoardIsGone(); } } } template typename T::ptr ObservedValuesContainer::get(const id _id) { LOG(3, "DEBUG: ObservedValuesContainer got get() for an observed value of " << NameOfType << " " << _id); typename CountedObservedValues_t::iterator iter = ObservedValues.find(_id); if (iter == ObservedValues.end()) return typename T::ptr(); else return iter->second.getCurrentValue().first; } template void ObservedValuesContainer::markObservedValuesAsConnected( const id _id) { LOG(3, "DEBUG: ObservedValuesContainer got markObservedValuesAsConnected() for an observed value of " << NameOfType << " " << _id); typename CountedObservedValues_t::iterator iter = ObservedValues.find(_id); ASSERT (iter != ObservedValues.end(), "ObservedValuesContainer::markObservedValuesAsConnected() - Observed value of " +NameOfType+" "+toString(_id)+" is not present yet."); ++(iter->second.getCurrentValue().second); } template bool ObservedValuesContainer::checkRefCount( const id _id) const { typename CountedObservedValues_t::const_iterator iter = ObservedValues.find(_id); return ((iter != ObservedValues.end()) && (iter->second.getEraseCandidate().second == 0)); } template void ObservedValuesContainer::markObservedValuesAsDisconnected( const id _id) { LOG(3, "DEBUG: ObservedValuesContainer got markObservedValuesAsDisconnected() for an observed value of " << NameOfType << " " << _id); typename CountedObservedValues_t::iterator iter = ObservedValues.find(_id); ASSERT (iter != ObservedValues.end(), "ObservedValuesContainer::markObservedValuesAsDisconnected() - Observed value of " +NameOfType+" "+toString(_id)+" is not present yet."); ASSERT (iter->second.getEraseCandidate().second != 0, "ObservedValuesContainer::markObservedValuesAsDisconnected() - Observed value of " +NameOfType+" "+toString(_id)+" is already signOff() from all."); --(iter->second.getEraseCandidate().second); if (checkRefCount(_id) && checksubjectKilled(_id) && checkMarkedForErase(_id)) removeObservedValues(_id); } template bool ObservedValuesContainer::checksubjectKilled( const id _id) const { typename subjectKilledCount_t::const_iterator iter = subjectKilledCount.find(_id); return ((iter != subjectKilledCount.end()) && (iter->second == T::MAX_ObservedTypes)); } template void ObservedValuesContainer::countsubjectKilled(const id _id) { LOG(3, "DEBUG: ObservedValuesContainer got subjectKilled() for an observed value of " << NameOfType << " " << _id); typename subjectKilledCount_t::iterator iter = subjectKilledCount.find(_id); if (iter == subjectKilledCount.end()) { std::pair inserter = subjectKilledCount.insert( std::make_pair(_id, 0) ); iter = inserter.first; } ASSERT (iter->second < T::MAX_ObservedTypes, "ObservedValuesContainer::countsubjectKilled() - all subjectKilled() for " +NameOfType+" "+toString(_id)+" for each observed channel came in already."); ++(iter->second); if (checkRefCount(_id) && checksubjectKilled(_id) && checkMarkedForErase(_id)) removeObservedValues(_id); } template void ObservedValuesContainer::removeObservedValues(const id _id) { LOG(3, "DEBUG: ObservedValuesContainer removes " << NameOfType << " " << _id); // call callback function onDestroy(_id); subjectKilledCount.erase(_id); typename CountedObservedValues_t::iterator iter = ObservedValues.find(_id); iter->second.eraseCurrentValue(); if (iter->second.empty()) ObservedValues.erase(iter); MarkedForErase.erase(_id); } template void ObservedValuesContainer::eraseObservedValues(const id _id) { #ifndef NDEBUG std::pair< typename std::set::iterator, bool > inserter = #endif MarkedForErase.insert(_id); ASSERT( inserter.second, "ObservedValuesContainer::eraseObservedValues() - received twice for " +NameOfType+" "+toString(_id)+"."); if (checkRefCount(_id) && checksubjectKilled(_id) && checkMarkedForErase(_id)) removeObservedValues(_id); } template bool ObservedValuesContainer::checkMarkedForErase(const id _id) const { return MarkedForErase.count(_id); } template void ObservedValuesContainer::insert(const id _id, const typename T::ptr &_obsvalues) { typename ObservedValuesContainer::RefCountedObserved::Value_t value(std::make_pair(_obsvalues,0)); typename CountedObservedValues_t::iterator iter = ObservedValues.find(_id); if (iter == ObservedValues.end()) { std::pair inserter = ObservedValues.insert( std::make_pair( _id, RefCountedObserved(value) ) ); ASSERT( inserter.second, "ObservedValuesContainer::insert() of "+NameOfType +" for "+toString(_id)+", insertion failed though empty?"); } else { ASSERT( !iter->second.empty(), "ObservedValuesContainer::insert() of "+NameOfType +" for "+toString(_id)+" has an empty list in ObservedValues."); // already an entry present? add to deque iter->second.push_back( value ); } _obsvalues->activateObserver(); } template bool ObservedValuesContainer::changeIdentifier(const id _oldid, const id _newid) { const typename CountedObservedValues_t::iterator Colditer = ObservedValues.find(_oldid); const typename CountedObservedValues_t::iterator Cnewiter = ObservedValues.find(_newid); const typename subjectKilledCount_t::iterator Solditer = subjectKilledCount.find(_oldid); const typename subjectKilledCount_t::iterator Snewiter = subjectKilledCount.find(_newid); const typename MarkedForErase_t::iterator Eolditer = MarkedForErase.find(_oldid); const typename MarkedForErase_t::iterator Enewiter = MarkedForErase.find(_newid); bool status = ((Colditer != ObservedValues.end()) && (Cnewiter == ObservedValues.end())); status &= ((Solditer != subjectKilledCount.end()) && (Snewiter == subjectKilledCount.end())); status &= ((Eolditer != MarkedForErase.end()) && (Enewiter == MarkedForErase.end())); // change id here only if still present if (status) { { // TODO: Actually, we need to think whether we do not have to to split the // deque in two parts: the last entry having the newid, while all other // ones retain the old one until they get removed. But we need to check // whether changing ids "there" is possible when the QtObserved... is under // removal. ObservedValuesContainer::RefCountedObserved obsvalues = Colditer->second; ObservedValues.erase(Colditer); ObservedValues.insert( std::make_pair(_newid, obsvalues) ); } { const size_t countvalue = Solditer->second; subjectKilledCount.erase(Solditer); subjectKilledCount.insert( std::make_pair(_newid, countvalue) ); } { MarkedForErase.erase(Eolditer); MarkedForErase.insert(_newid); } return true; } else return false; } template bool ObservedValuesContainer::isPresent(const id _id) const { typename CountedObservedValues_t::const_iterator iter = ObservedValues.find(_id); return (iter != ObservedValues.end()); } #endif /* OBSERVEDVALUESCONTAINER_IMPL_HPP_ */