Forward port from CVS/PLIB: Use a more memory allocation efficient replay
system.
This commit is contained in:
parent
78e6655002
commit
78aaa1ce7a
2 changed files with 114 additions and 54 deletions
|
@ -56,7 +56,26 @@ FGReplay::FGReplay() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FGReplay::~FGReplay() {
|
FGReplay::~FGReplay() {
|
||||||
// no dynamically allocated memory to free
|
while ( !short_term.empty() ) {
|
||||||
|
//cerr << "Deleting Short term" <<endl;
|
||||||
|
delete short_term.front();
|
||||||
|
short_term.pop_front();
|
||||||
|
}
|
||||||
|
while ( !medium_term.empty() ) {
|
||||||
|
//cerr << "Deleting Medium term" <<endl;
|
||||||
|
delete medium_term.front();
|
||||||
|
medium_term.pop_front();
|
||||||
|
}
|
||||||
|
while ( !long_term.empty() ) {
|
||||||
|
//cerr << "Deleting Long term" <<endl;
|
||||||
|
delete long_term.front();
|
||||||
|
long_term.pop_front();
|
||||||
|
}
|
||||||
|
while ( !recycler.empty() ) {
|
||||||
|
//cerr << "Deleting Recycler" <<endl;
|
||||||
|
delete recycler.front();
|
||||||
|
recycler.pop_front();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,13 +90,28 @@ void FGReplay::init() {
|
||||||
|
|
||||||
// Make sure all queues are flushed
|
// Make sure all queues are flushed
|
||||||
while ( !short_term.empty() ) {
|
while ( !short_term.empty() ) {
|
||||||
|
delete short_term.front();
|
||||||
short_term.pop_front();
|
short_term.pop_front();
|
||||||
}
|
}
|
||||||
while ( !medium_term.empty() ) {
|
while ( !medium_term.empty() ) {
|
||||||
|
delete medium_term.front();
|
||||||
medium_term.pop_front();
|
medium_term.pop_front();
|
||||||
}
|
}
|
||||||
while ( !medium_term.empty() ) {
|
while ( !long_term.empty() ) {
|
||||||
medium_term.pop_front();
|
delete long_term.front();
|
||||||
|
long_term.pop_front();
|
||||||
|
}
|
||||||
|
while ( !recycler.empty() ) {
|
||||||
|
delete recycler.front();
|
||||||
|
recycler.pop_front();
|
||||||
|
}
|
||||||
|
// Create an estimated nr of required ReplayData objects
|
||||||
|
// 120 is an estimated maximum frame rate.
|
||||||
|
int estNrObjects = (int) ((st_list_time*120) + (mt_list_time*mt_dt) +
|
||||||
|
(lt_list_time*lt_dt));
|
||||||
|
for (int i = 0; i < estNrObjects; i++) {
|
||||||
|
recycler.push_back(new FGReplayData);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +139,8 @@ void FGReplay::unbind() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void FGReplay::update( double dt ) {
|
void FGReplay::update( double dt ) {
|
||||||
|
timingInfo.clear();
|
||||||
|
stamp("begin");
|
||||||
static SGPropertyNode *replay_master
|
static SGPropertyNode *replay_master
|
||||||
= fgGetNode( "/sim/freeze/replay", true );
|
= fgGetNode( "/sim/freeze/replay", true );
|
||||||
|
|
||||||
|
@ -115,62 +151,84 @@ void FGReplay::update( double dt ) {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//stamp("point_01");
|
||||||
if ( replay_master->getBoolValue() ) {
|
if ( replay_master->getBoolValue() ) {
|
||||||
// don't record the replay session
|
// don't record the replay session
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//cerr << "Recording replay" << endl;
|
||||||
sim_time += dt;
|
sim_time += dt;
|
||||||
|
|
||||||
// build the replay record
|
// build the replay record
|
||||||
FGNetFDM f;
|
//FGNetFDM f;
|
||||||
FGProps2NetFDM( &f, false );
|
//FGProps2NetFDM( &f, false );
|
||||||
|
|
||||||
// sanity check, don't collect data if FDM data isn't good
|
// sanity check, don't collect data if FDM data isn't good
|
||||||
if ( !cur_fdm_state->get_inited() ) {
|
if ( !cur_fdm_state->get_inited() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//FGNetCtrls c;
|
||||||
FGNetCtrls c;
|
//FGProps2NetCtrls( &c, false, false );
|
||||||
FGProps2NetCtrls( &c, false, false );
|
//stamp("point_04ba");
|
||||||
|
FGReplayData *r;
|
||||||
FGReplayData r;
|
//stamp("point_04bb");
|
||||||
r.sim_time = sim_time;
|
if (!recycler.size()) {
|
||||||
r.ctrls = c;
|
stamp("Replay_01");
|
||||||
r.fdm = f;
|
r = new FGReplayData;
|
||||||
|
stamp("Replay_02");
|
||||||
|
} else {
|
||||||
|
r = recycler.front();
|
||||||
|
recycler.pop_front();
|
||||||
|
//stamp("point_04be");
|
||||||
|
}
|
||||||
|
r->sim_time = sim_time;
|
||||||
|
//r->ctrls = c;
|
||||||
|
//stamp("point_04e");
|
||||||
|
FGProps2NetFDM( &(r->fdm), false );
|
||||||
|
FGProps2NetCtrls( &(r->ctrls), false, false );
|
||||||
|
//r->fdm = f;
|
||||||
|
//stamp("point_05");
|
||||||
|
|
||||||
// update the short term list
|
// update the short term list
|
||||||
|
//stamp("point_06");
|
||||||
short_term.push_back( r );
|
short_term.push_back( r );
|
||||||
|
//stamp("point_07");
|
||||||
FGReplayData st_front = short_term.front();
|
FGReplayData *st_front = short_term.front();
|
||||||
if ( sim_time - st_front.sim_time > st_list_time ) {
|
if ( sim_time - st_front->sim_time > st_list_time ) {
|
||||||
while ( sim_time - st_front.sim_time > st_list_time ) {
|
while ( sim_time - st_front->sim_time > st_list_time ) {
|
||||||
st_front = short_term.front();
|
st_front = short_term.front();
|
||||||
|
recycler.push_back(st_front);
|
||||||
short_term.pop_front();
|
short_term.pop_front();
|
||||||
}
|
}
|
||||||
|
//stamp("point_08");
|
||||||
// update the medium term list
|
// update the medium term list
|
||||||
if ( sim_time - last_mt_time > mt_dt ) {
|
if ( sim_time - last_mt_time > mt_dt ) {
|
||||||
last_mt_time = sim_time;
|
last_mt_time = sim_time;
|
||||||
|
st_front = short_term.front();
|
||||||
medium_term.push_back( st_front );
|
medium_term.push_back( st_front );
|
||||||
|
short_term.pop_front();
|
||||||
|
|
||||||
FGReplayData mt_front = medium_term.front();
|
FGReplayData *mt_front = medium_term.front();
|
||||||
if ( sim_time - mt_front.sim_time > mt_list_time ) {
|
if ( sim_time - mt_front->sim_time > mt_list_time ) {
|
||||||
while ( sim_time - mt_front.sim_time > mt_list_time ) {
|
//stamp("point_09");
|
||||||
|
while ( sim_time - mt_front->sim_time > mt_list_time ) {
|
||||||
mt_front = medium_term.front();
|
mt_front = medium_term.front();
|
||||||
|
recycler.push_back(mt_front);
|
||||||
medium_term.pop_front();
|
medium_term.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the long term list
|
// update the long term list
|
||||||
if ( sim_time - last_lt_time > lt_dt ) {
|
if ( sim_time - last_lt_time > lt_dt ) {
|
||||||
last_lt_time = sim_time;
|
last_lt_time = sim_time;
|
||||||
|
mt_front = medium_term.front();
|
||||||
long_term.push_back( mt_front );
|
long_term.push_back( mt_front );
|
||||||
|
medium_term.pop_front();
|
||||||
|
|
||||||
FGReplayData lt_front = long_term.front();
|
FGReplayData *lt_front = long_term.front();
|
||||||
if ( sim_time - lt_front.sim_time > lt_list_time ) {
|
if ( sim_time - lt_front->sim_time > lt_list_time ) {
|
||||||
while ( sim_time - lt_front.sim_time > lt_list_time ) {
|
//stamp("point_10");
|
||||||
|
while ( sim_time - lt_front->sim_time > lt_list_time ) {
|
||||||
lt_front = long_term.front();
|
lt_front = long_term.front();
|
||||||
|
recycler.push_back(lt_front);
|
||||||
long_term.pop_front();
|
long_term.pop_front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,6 +248,7 @@ void FGReplay::update( double dt ) {
|
||||||
<< " time = " << sim_time - long_term.front().sim_time
|
<< " time = " << sim_time - long_term.front().sim_time
|
||||||
<< endl;
|
<< endl;
|
||||||
#endif
|
#endif
|
||||||
|
//stamp("point_finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -409,7 +468,7 @@ static void interpolate( double time, const replay_list_type &list ) {
|
||||||
return;
|
return;
|
||||||
} else if ( list.size() == 1 ) {
|
} else if ( list.size() == 1 ) {
|
||||||
// handle list size == 1
|
// handle list size == 1
|
||||||
update_fdm( list[0] );
|
update_fdm( (*list[0]) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,11 +482,11 @@ static void interpolate( double time, const replay_list_type &list ) {
|
||||||
// cout << " " << first << " <=> " << last << endl;
|
// cout << " " << first << " <=> " << last << endl;
|
||||||
if ( last == first ) {
|
if ( last == first ) {
|
||||||
done = true;
|
done = true;
|
||||||
} else if ( list[mid].sim_time < time && list[mid+1].sim_time < time ) {
|
} else if ( list[mid]->sim_time < time && list[mid+1]->sim_time < time ) {
|
||||||
// too low
|
// too low
|
||||||
first = mid;
|
first = mid;
|
||||||
mid = ( last + first ) / 2;
|
mid = ( last + first ) / 2;
|
||||||
} else if ( list[mid].sim_time > time && list[mid+1].sim_time > time ) {
|
} else if ( list[mid]->sim_time > time && list[mid+1]->sim_time > time ) {
|
||||||
// too high
|
// too high
|
||||||
last = mid;
|
last = mid;
|
||||||
mid = ( last + first ) / 2;
|
mid = ( last + first ) / 2;
|
||||||
|
@ -436,7 +495,7 @@ static void interpolate( double time, const replay_list_type &list ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FGReplayData result = interpolate( time, list[mid], list[mid+1] );
|
FGReplayData result = interpolate( time, (*list[mid]), (*list[mid+1]) );
|
||||||
|
|
||||||
update_fdm( result );
|
update_fdm( result );
|
||||||
}
|
}
|
||||||
|
@ -453,60 +512,60 @@ void FGReplay::replay( double time ) {
|
||||||
double t1, t2;
|
double t1, t2;
|
||||||
|
|
||||||
if ( short_term.size() > 0 ) {
|
if ( short_term.size() > 0 ) {
|
||||||
t1 = short_term.back().sim_time;
|
t1 = short_term.back()->sim_time;
|
||||||
t2 = short_term.front().sim_time;
|
t2 = short_term.front()->sim_time;
|
||||||
if ( time > t1 ) {
|
if ( time > t1 ) {
|
||||||
// replay the most recent frame
|
// replay the most recent frame
|
||||||
update_fdm( short_term.back() );
|
update_fdm( (*short_term.back()) );
|
||||||
// cout << "first frame" << endl;
|
// cout << "first frame" << endl;
|
||||||
} else if ( time <= t1 && time >= t2 ) {
|
} else if ( time <= t1 && time >= t2 ) {
|
||||||
interpolate( time, short_term );
|
interpolate( time, short_term );
|
||||||
// cout << "from short term" << endl;
|
// cout << "from short term" << endl;
|
||||||
} else if ( medium_term.size() > 0 ) {
|
} else if ( medium_term.size() > 0 ) {
|
||||||
t1 = short_term.front().sim_time;
|
t1 = short_term.front()->sim_time;
|
||||||
t2 = medium_term.back().sim_time;
|
t2 = medium_term.back()->sim_time;
|
||||||
if ( time <= t1 && time >= t2 ) {
|
if ( time <= t1 && time >= t2 ) {
|
||||||
FGReplayData result = interpolate( time,
|
FGReplayData result = interpolate( time,
|
||||||
medium_term.back(),
|
(*medium_term.back()),
|
||||||
short_term.front() );
|
(*short_term.front()) );
|
||||||
update_fdm( result );
|
update_fdm( result );
|
||||||
// cout << "from short/medium term" << endl;
|
// cout << "from short/medium term" << endl;
|
||||||
} else {
|
} else {
|
||||||
t1 = medium_term.back().sim_time;
|
t1 = medium_term.back()->sim_time;
|
||||||
t2 = medium_term.front().sim_time;
|
t2 = medium_term.front()->sim_time;
|
||||||
if ( time <= t1 && time >= t2 ) {
|
if ( time <= t1 && time >= t2 ) {
|
||||||
interpolate( time, medium_term );
|
interpolate( time, medium_term );
|
||||||
// cout << "from medium term" << endl;
|
// cout << "from medium term" << endl;
|
||||||
} else if ( long_term.size() > 0 ) {
|
} else if ( long_term.size() > 0 ) {
|
||||||
t1 = medium_term.front().sim_time;
|
t1 = medium_term.front()->sim_time;
|
||||||
t2 = long_term.back().sim_time;
|
t2 = long_term.back()->sim_time;
|
||||||
if ( time <= t1 && time >= t2 ) {
|
if ( time <= t1 && time >= t2 ) {
|
||||||
FGReplayData result = interpolate( time,
|
FGReplayData result = interpolate( time,
|
||||||
long_term.back(),
|
(*long_term.back()),
|
||||||
medium_term.front());
|
(*medium_term.front()));
|
||||||
update_fdm( result );
|
update_fdm( result );
|
||||||
// cout << "from medium/long term" << endl;
|
// cout << "from medium/long term" << endl;
|
||||||
} else {
|
} else {
|
||||||
t1 = long_term.back().sim_time;
|
t1 = long_term.back()->sim_time;
|
||||||
t2 = long_term.front().sim_time;
|
t2 = long_term.front()->sim_time;
|
||||||
if ( time <= t1 && time >= t2 ) {
|
if ( time <= t1 && time >= t2 ) {
|
||||||
interpolate( time, long_term );
|
interpolate( time, long_term );
|
||||||
// cout << "from long term" << endl;
|
// cout << "from long term" << endl;
|
||||||
} else {
|
} else {
|
||||||
// replay the oldest long term frame
|
// replay the oldest long term frame
|
||||||
update_fdm( long_term.front() );
|
update_fdm( (*long_term.front()) );
|
||||||
// cout << "oldest long term frame" << endl;
|
// cout << "oldest long term frame" << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// replay the oldest medium term frame
|
// replay the oldest medium term frame
|
||||||
update_fdm( medium_term.front() );
|
update_fdm( (*medium_term.front()) );
|
||||||
// cout << "oldest medium term frame" << endl;
|
// cout << "oldest medium term frame" << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// replay the oldest short term frame
|
// replay the oldest short term frame
|
||||||
update_fdm( short_term.front() );
|
update_fdm( (*short_term.front()) );
|
||||||
// cout << "oldest short term frame" << endl;
|
// cout << "oldest short term frame" << endl;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -517,11 +576,11 @@ void FGReplay::replay( double time ) {
|
||||||
|
|
||||||
double FGReplay::get_start_time() {
|
double FGReplay::get_start_time() {
|
||||||
if ( long_term.size() > 0 ) {
|
if ( long_term.size() > 0 ) {
|
||||||
return long_term.front().sim_time;
|
return (*long_term.front()).sim_time;
|
||||||
} else if ( medium_term.size() > 0 ) {
|
} else if ( medium_term.size() > 0 ) {
|
||||||
return medium_term.front().sim_time;
|
return (*medium_term.front()).sim_time;
|
||||||
} else if ( short_term.size() ) {
|
} else if ( short_term.size() ) {
|
||||||
return short_term.front().sim_time;
|
return (*short_term.front()).sim_time;
|
||||||
} else {
|
} else {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
@ -529,7 +588,7 @@ double FGReplay::get_start_time() {
|
||||||
|
|
||||||
double FGReplay::get_end_time() {
|
double FGReplay::get_end_time() {
|
||||||
if ( short_term.size() ) {
|
if ( short_term.size() ) {
|
||||||
return short_term.back().sim_time;
|
return (*short_term.back()).sim_time;
|
||||||
} else {
|
} else {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ public:
|
||||||
FGNetCtrls ctrls;
|
FGNetCtrls ctrls;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef deque < FGReplayData > replay_list_type;
|
typedef deque < FGReplayData *> replay_list_type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@ private:
|
||||||
replay_list_type short_term;
|
replay_list_type short_term;
|
||||||
replay_list_type medium_term;
|
replay_list_type medium_term;
|
||||||
replay_list_type long_term;
|
replay_list_type long_term;
|
||||||
|
replay_list_type recycler;
|
||||||
SGPropertyNode_ptr disable_replay;
|
SGPropertyNode_ptr disable_replay;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue