I have a queue of audio elements for each frame of a movie. I want to remove them from last seen to first seen up to a certain max number of elements. I use timeval to determine the time value. I have problems with the iterators due to calling erase on the elements.
I tried creating a std::multimap to store all the iterators based on the timeval key. Then I stored all the iterators on a vector based on max_frames to remove. I then sorted the vector of iterators from greater to less. Then erased all iterators.
// C++
void CMedia::timed_limit_audio_store(const int64_t frame)
{
unsigned max_frames = max_audio_frames();
struct customMore {
inline bool operator()( const timeval& a,
const timeval& b ) const
{
return (((a).tv_sec == (b).tv_sec) ?
((a).tv_usec > (b).tv_usec) :
(a).tv_sec > (b).tv_sec)));
}
};
typedef std::multimap< timeval, audio_cache_t::iterator,
customMore > TimedSeqMap;
TimedSeqMap tmp;
{
audio_cache_t::iterator it = _audio.begin();
audio_cache_t::iterator end = _audio.end();
for ( ; it != end; ++it )
{
if ( (*it)->frame() - max_frames < frame )
tmp.insert( std::make_pair( (*it)->ptime(), it ) );
}
}
unsigned count = 0;
TimedSeqMap::iterator it = tmp.begin();
typedef std::vector< audio_cache_t::iterator > IteratorList;
IteratorList iters;
for ( ; it != tmp.end(); ++it )
{
++count;
if ( count > max_frames )
{
// Store this iterator to remove it later
iters.push_back( it->second );
}
}
IteratorList::iterator i = iters.begin();
IteratorList::iterator e = iters.end();
// We sort the iterators from bigger to smaller to avoid erase
// trashing our iterator. However, this is not working properly.
std::sort( i, e, std::greater<audio_cache_t::iterator>() );
i = iters.begin();
e = iters.end();
for ( ; i != e; ++i )
{
_audio.erase( *i );
}
}
The expected result would be that the vector's elements are removed based on the timeval of the audio elements. The actual errors are memory trashing and sometimes crashes.