/* * 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" #include template ObservedValuesContainer::ObservedValuesContainer( const std::string _name, QtObservedInstanceBoard &_board, const onDestroy_t _onDestroy) : NameOfType(_name), board(_board), onDestroy(_onDestroy) {} template ObservedValuesContainer::~ObservedValuesContainer() { boost::recursive_mutex::scoped_lock lock(atomic_mutex); 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 #ifdef HAVE_INLINE inline #endif void ObservedValuesContainer::checkRemoval(const id _id) { if (checkRefCount(_id) && checkMarkedForErase(_id)) removeObservedValues(_id); } template typename T::ptr ObservedValuesContainer::get(const id _id) { boost::recursive_mutex::scoped_lock lock(atomic_mutex); 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) { boost::recursive_mutex::scoped_lock lock(atomic_mutex); 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 { boost::recursive_mutex::scoped_lock lock(atomic_mutex); 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) { boost::recursive_mutex::scoped_lock lock(atomic_mutex); 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); checkRemoval(_id); } template void ObservedValuesContainer::removeObservedValues(const id _id) { boost::recursive_mutex::scoped_lock lock(atomic_mutex); LOG(3, "DEBUG: ObservedValuesContainer removes " << NameOfType << " " << _id); // call callback function onDestroy(_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) { boost::recursive_mutex::scoped_lock lock(atomic_mutex); #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)+"."); checkRemoval(_id); } template #ifdef HAVE_INLINE inline #endif bool ObservedValuesContainer::checkMarkedForErase(const id _id) const { boost::recursive_mutex::scoped_lock lock(atomic_mutex); return MarkedForErase.count(_id); } template void ObservedValuesContainer::insert(const id _id, const typename T::ptr &_obsvalues) { boost::recursive_mutex::scoped_lock lock(atomic_mutex); 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) { boost::recursive_mutex::scoped_lock lock(atomic_mutex); const typename CountedObservedValues_t::iterator Colditer = ObservedValues.find(_oldid); const typename CountedObservedValues_t::iterator Cnewiter = ObservedValues.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 &= ((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) ); } { MarkedForErase.erase(Eolditer); MarkedForErase.insert(_newid); } return true; } else return false; } template #ifdef HAVE_INLINE inline #endif bool ObservedValuesContainer::isPresent(const id _id) const { boost::recursive_mutex::scoped_lock lock(atomic_mutex); typename CountedObservedValues_t::const_iterator iter = ObservedValues.find(_id); return (iter != ObservedValues.end()); } #endif /* OBSERVEDVALUESCONTAINER_IMPL_HPP_ */