out over multiple frames.
}
+// Return the index of the oldest tile in the cache, return -1 if
+// nothing available to be removed.
+long FGNewCache::get_oldest_tile() {
+ // we need to free the furthest entry
+ long max_index = -1;
+ double timestamp = 0.0;
+ double min_time = 2419200000.0f; // one month should be enough
+ double max_time = 0;
+
+ tile_map_iterator current = tile_cache.begin();
+ tile_map_iterator end = tile_cache.end();
+
+ for ( ; current != end; ++current ) {
+ long index = current->first;
+ FGTileEntry *e = current->second;
+ if ( e->is_loaded() && (e->get_pending_models() == 0) ) {
+
+ timestamp = e->get_timestamp();
+ if ( timestamp < min_time ) {
+ max_index = index;
+ min_time = timestamp;
+ }
+ if ( timestamp > max_time ) {
+ max_time = timestamp;
+ }
+
+ } else {
+ SG_LOG( SG_TERRAIN, SG_DEBUG, "loaded = " << e->is_loaded()
+ << " pending models = " << e->get_pending_models()
+ << " time stamp = " << e->get_timestamp() );
+ }
+ }
+
+ SG_LOG( SG_TERRAIN, SG_INFO, " min_time = " << min_time );
+ SG_LOG( SG_TERRAIN, SG_INFO, " index = " << max_index );
+ SG_LOG( SG_TERRAIN, SG_INFO, " max_time = " << max_time );
+
+ return max_index;
+}
+
+
+// Clear a cache entry, note that the cache only holds pointers
+// and this does not free the object which is pointed to.
+void FGNewCache::clear_entry( long cache_index ) {
+ tile_cache.erase( cache_index );
+}
+
+
// Clear all completely loaded tiles (ignores partially loaded tiles)
void FGNewCache::clear_cache() {
// Ensure at least one entry is free in the cache
bool make_space();
+ // Return the index of the oldest tile in the cache, return -1 if
+ // nothing available to be removed.
+ long get_oldest_tile();
+
+ // Clear a cache entry, note that the cache only holds pointers
+ // and this does not free the object which is pointed to.
+ void clear_entry( long cache_entry );
+
// Clear all completely loaded tiles (ignores partially loaded tiles)
void clear_cache();
queue<FGTileEntry *> FGTileMgr::attach_queue;
queue<FGDeferredModel *> FGTileMgr::model_queue;
#endif // ENABLE_THREADS
+queue<FGTileEntry *> FGTileMgr::delete_queue;
// Constructor
state( Start ),
current_tile( NULL ),
vis( 16000 ),
- counter_hack(0)
+ counter_hack(0),
+ max_cache_size(100)
{
}
FGTileEntry *t = tile_cache.get_tile( b );
if ( t == NULL ) {
+ // make space in the cache
+ while ( tile_cache.get_size() > max_cache_size ) {
+ long index = tile_cache.get_oldest_tile();
+ if ( index >= 0 ) {
+ FGTileEntry *old = tile_cache.get_tile( index );
+ delete_queue.push( old );
+ tile_cache.clear_entry( index );
+ } else {
+ // nothing to free ?!? forge ahead
+ break;
+ }
+ }
+
// create a new entry
FGTileEntry *e = new FGTileEntry( b );
// cout << "xrange = " << xrange << " yrange = " << yrange << endl;
// note * 2 at end doubles cache size (for fdm and viewer)
- tile_cache.set_max_cache_size( (2*xrange + 2) * (2*yrange + 2) * 2 );
+ max_cache_size = (2*xrange + 2) * (2*yrange + 2) * 2;
SGBucket b;
// cout << "Adding ssg nodes for "
}
+ if ( !delete_queue.empty() ) {
+ FGTileEntry* e = delete_queue.front();
+ delete_queue.pop();
+ e->disconnect_ssg_nodes();
+ e->free_tile();
+ delete e;
+ }
+
// no reason to update this if we haven't moved...
if ( longitude != last_longitude || latitude != last_latitude ) {
// update current elevation...
// timer event driven call to scheduler for the purpose of refreshing the tile timestamps
void FGTileMgr::refresh_view_timestamps() {
- SG_LOG( SG_TERRAIN, SG_INFO,
- "Refreshing timestamps for " << current_bucket.get_center_lon() << " " << current_bucket.get_center_lat() );
- schedule_needed(fgGetDouble("/environment/visibility-m"), current_bucket);
+ SG_LOG( SG_TERRAIN, SG_INFO,
+ "Refreshing timestamps for " << current_bucket.get_center_lon()
+ << " " << current_bucket.get_center_lat() );
+ schedule_needed(fgGetDouble("/environment/visibility-m"), current_bucket);
}
// check and set current tile and scenery center...
/**
* tile cache
*/
+ int max_cache_size;
FGNewCache tile_cache;
/**
static queue<FGTileEntry *> attach_queue;
static queue<FGDeferredModel *> model_queue;
#endif // ENABLE_THREADS
+ static queue<FGTileEntry *> delete_queue;
public:
*/
static void ready_to_attach( FGTileEntry *t ) { attach_queue.push( t ); }
-#ifdef WISH_PLIB_WAS_THREADED // but it isn't
- /**
- * Tile is detatched from scene graph and is ready to delete
- */
- inline void ready_to_delete( FGTileEntry *t ) { loader.remove( t ); }
-#endif
-
/**
* Add a pending model to the 'deferred model load' queue
*/