N
neil.johnston
I have a cut down example program that uses multiset to order some
data. The data arrives from various sources and has a time stamp, data
with identical timestamps can arrive and due to fifo's and block sizes
data from one source with a later time stamp may arrive before data
from another source with and earlier time stamp.
Looking at the STL i thought multiset was just the job for this. The
idea was to set a window of x seconds and read out data older than
this from the multiset.
This works fine, except that the memory image just increases forever
and with data arriving without end this is not a good outcome.
I can't see where i'm going wrong, maybe multiset is not designed for
this job or i've gone blind to the obvious error.
Any pointers on what the problems is or alternative implementations
much appreciated.
cheers
neil
Here's the cut down code (sorry about the size of this post):
/*
* test of a multiset
* - problem is that it leaks like a waterfall
*/
#include <iostream>
#include <set>
// A class to hold data and an associated timestamp
// we are given a pointer to the data, we do not copy it on entry or
retrieval
class TimedStore {
public:
TimedStore(unsigned char **data, unsigned long long TS)
{ _data=*data; *data=0L; _TS=TS; };
~TimedStore() {}; // don't delete [] _data here as would accidently
destroy it on multiset erase()
void getData(unsigned char **data) const { *data=_data; return; };
unsigned long long getTS() const { return(_TS); };
bool operator < (const TimedStore &ref) const { return(this->_TS <
ref._TS); };
private:
unsigned long long _TS;
unsigned char *_data;
};
// for multiset compare as we store pointers to the TimeStore objects
struct classcomp {
bool operator() (const TimedStore *lhs, const TimedStore *rhs) const
{return *lhs < *rhs;}
};
int main ()
{
unsigned char *tt;
unsigned long long time=1000; // don't want -ve time
std::multiset<TimedStore *, classcomp> _ordered;
// put some data in, we would run this forever normaly
// data would be arriving from different places with different fifo
and block sizes
// hence data would not be in the correct time order
for(int t=0; t<1000000; t++)
{
// a random, generally incrementing, timestamp
int inc=rand()/(RAND_MAX/7);
int inc2=(rand()/(RAND_MAX/9));
time=time+(((inc>1)?1:-1)*inc2);
tt=new unsigned char[102]; // some test data
//std::cout << time << " " << std::hex << (unsigned long)tt <<
std::dec << std::endl;
TimedStore *tmp=new TimedStore(&tt, time);
_ordered.insert(tmp);
}
std::cout << "inserted - sleep(5), check memory footprint" <<
std::endl;
sleep(5);
// now lets get the ordered data out, we would normaly do this on
insertion
// with a window set to get the order correct over a time window
while(!_ordered.empty())
{
std::multiset<TimedStore *>::iterator old=_ordered.begin();
TimedStore *tmp=*old;
time=tmp->getTS();
tmp->getData(&tt);
_ordered.erase(old); // delete it from the multiset
//std::cout << time << " " << std::hex << (unsigned long)tt <<
std::dec << std::endl;
delete [] tt; // destroy the data
}
std::cout << "erased/deleted - sleep(5), check memory footprint" <<
std::endl;
sleep(5);
_ordered.clear();
std::cout << "cleared - sleep(5), check memory footprint" <<
std::endl;
sleep(5);
std::cout << "exit" << std::endl;
return 0;
}
data. The data arrives from various sources and has a time stamp, data
with identical timestamps can arrive and due to fifo's and block sizes
data from one source with a later time stamp may arrive before data
from another source with and earlier time stamp.
Looking at the STL i thought multiset was just the job for this. The
idea was to set a window of x seconds and read out data older than
this from the multiset.
This works fine, except that the memory image just increases forever
and with data arriving without end this is not a good outcome.
I can't see where i'm going wrong, maybe multiset is not designed for
this job or i've gone blind to the obvious error.
Any pointers on what the problems is or alternative implementations
much appreciated.
cheers
neil
Here's the cut down code (sorry about the size of this post):
/*
* test of a multiset
* - problem is that it leaks like a waterfall
*/
#include <iostream>
#include <set>
// A class to hold data and an associated timestamp
// we are given a pointer to the data, we do not copy it on entry or
retrieval
class TimedStore {
public:
TimedStore(unsigned char **data, unsigned long long TS)
{ _data=*data; *data=0L; _TS=TS; };
~TimedStore() {}; // don't delete [] _data here as would accidently
destroy it on multiset erase()
void getData(unsigned char **data) const { *data=_data; return; };
unsigned long long getTS() const { return(_TS); };
bool operator < (const TimedStore &ref) const { return(this->_TS <
ref._TS); };
private:
unsigned long long _TS;
unsigned char *_data;
};
// for multiset compare as we store pointers to the TimeStore objects
struct classcomp {
bool operator() (const TimedStore *lhs, const TimedStore *rhs) const
{return *lhs < *rhs;}
};
int main ()
{
unsigned char *tt;
unsigned long long time=1000; // don't want -ve time
std::multiset<TimedStore *, classcomp> _ordered;
// put some data in, we would run this forever normaly
// data would be arriving from different places with different fifo
and block sizes
// hence data would not be in the correct time order
for(int t=0; t<1000000; t++)
{
// a random, generally incrementing, timestamp
int inc=rand()/(RAND_MAX/7);
int inc2=(rand()/(RAND_MAX/9));
time=time+(((inc>1)?1:-1)*inc2);
tt=new unsigned char[102]; // some test data
//std::cout << time << " " << std::hex << (unsigned long)tt <<
std::dec << std::endl;
TimedStore *tmp=new TimedStore(&tt, time);
_ordered.insert(tmp);
}
std::cout << "inserted - sleep(5), check memory footprint" <<
std::endl;
sleep(5);
// now lets get the ordered data out, we would normaly do this on
insertion
// with a window set to get the order correct over a time window
while(!_ordered.empty())
{
std::multiset<TimedStore *>::iterator old=_ordered.begin();
TimedStore *tmp=*old;
time=tmp->getTS();
tmp->getData(&tt);
_ordered.erase(old); // delete it from the multiset
//std::cout << time << " " << std::hex << (unsigned long)tt <<
std::dec << std::endl;
delete [] tt; // destroy the data
}
std::cout << "erased/deleted - sleep(5), check memory footprint" <<
std::endl;
sleep(5);
_ordered.clear();
std::cout << "cleared - sleep(5), check memory footprint" <<
std::endl;
sleep(5);
std::cout << "exit" << std::endl;
return 0;
}