From 96d499f4f15ebd5c94b5a59d3f536e4202bba1e0 Mon Sep 17 00:00:00 2001 From: curt Date: Thu, 25 Jul 2002 21:57:58 +0000 Subject: [PATCH] Restructuring how tiles are freed to allow us to eventually spread the task out over multiple frames. --- src/Scenery/newcache.cxx | 48 ++++++++++++++++++++++++++++++++++++++++ src/Scenery/newcache.hxx | 8 +++++++ src/Scenery/tilemgr.cxx | 34 +++++++++++++++++++++++----- src/Scenery/tilemgr.hxx | 9 ++------ 4 files changed, 87 insertions(+), 12 deletions(-) diff --git a/src/Scenery/newcache.cxx b/src/Scenery/newcache.cxx index 98122377c..9e1040d3d 100644 --- a/src/Scenery/newcache.cxx +++ b/src/Scenery/newcache.cxx @@ -171,6 +171,54 @@ bool FGNewCache::make_space() { } +// 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() { diff --git a/src/Scenery/newcache.hxx b/src/Scenery/newcache.hxx index 4a10884bd..8060a1bec 100644 --- a/src/Scenery/newcache.hxx +++ b/src/Scenery/newcache.hxx @@ -85,6 +85,14 @@ public: // 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(); diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index 53d2d6d4e..2d3dd9dda 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -62,6 +62,7 @@ SGLockedQueue FGTileMgr::model_queue; queue FGTileMgr::attach_queue; queue FGTileMgr::model_queue; #endif // ENABLE_THREADS +queue FGTileMgr::delete_queue; // Constructor @@ -69,7 +70,8 @@ FGTileMgr::FGTileMgr(): state( Start ), current_tile( NULL ), vis( 16000 ), - counter_hack(0) + counter_hack(0), + max_cache_size(100) { } @@ -128,6 +130,19 @@ void FGTileMgr::sched_tile( const SGBucket& b ) { 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 ); @@ -174,7 +189,7 @@ void FGTileMgr::schedule_needed( double vis, SGBucket curr_bucket) { // 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; @@ -345,6 +360,14 @@ int FGTileMgr::update( double lon, double lat, double visibility_meters, // 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... @@ -363,9 +386,10 @@ int FGTileMgr::update( double lon, double lat, double visibility_meters, // 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... diff --git a/src/Scenery/tilemgr.hxx b/src/Scenery/tilemgr.hxx index 9eebc5dcb..714bafa76 100644 --- a/src/Scenery/tilemgr.hxx +++ b/src/Scenery/tilemgr.hxx @@ -105,6 +105,7 @@ private: /** * tile cache */ + int max_cache_size; FGNewCache tile_cache; /** @@ -129,6 +130,7 @@ private: static queue attach_queue; static queue model_queue; #endif // ENABLE_THREADS + static queue delete_queue; public: @@ -137,13 +139,6 @@ 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 */