From d5a2533411722827d98e6103d383ae4c28f7350b Mon Sep 17 00:00:00 2001 From: curt Date: Wed, 30 May 2001 18:21:03 +0000 Subject: [PATCH] Fixed a bug in the tile pager / caching / management system that caused a crash when relocating to a new airport. Pending work from the old area is now just completed as normal, rather than trying to empty the various queues in their various stages when can lead to many problems in a threaded environment. --- src/Scenery/FGTileLoader.cxx | 8 +++--- src/Scenery/FGTileLoader.hxx | 2 ++ src/Scenery/newcache.cxx | 52 +++++++++++++++++++++--------------- src/Scenery/newcache.hxx | 3 +++ src/Scenery/tileentry.cxx | 14 +++++++++- src/Scenery/tilemgr.cxx | 28 +++++-------------- src/Scenery/tilemgr.hxx | 5 ---- 7 files changed, 61 insertions(+), 51 deletions(-) diff --git a/src/Scenery/FGTileLoader.cxx b/src/Scenery/FGTileLoader.cxx index a27d79dd7..69338c03b 100644 --- a/src/Scenery/FGTileLoader.cxx +++ b/src/Scenery/FGTileLoader.cxx @@ -65,6 +65,7 @@ FGTileLoader::~FGTileLoader() } +#if 0 // we don't ever want to do this I don't think /** * */ @@ -73,6 +74,7 @@ void FGTileLoader::reinit() { tile_load_queue.pop(); } } +#endif /** @@ -125,7 +127,7 @@ FGTileLoader::update() mutex.unlock(); #else if ( !tile_load_queue.empty() ) { - cout << "loading next tile ..." << endl; + // cout << "loading next tile ..." << endl; // load the next tile in the queue FGTileEntry* tile = tile_load_queue.front(); tile_load_queue.pop(); @@ -135,7 +137,7 @@ FGTileLoader::update() #ifdef WISH_PLIB_WAS_THREADED // but it isn't if ( !tile_free_queue.empty() ) { - cout << "freeing next tile ..." << endl; + // cout << "freeing next tile ..." << endl; // free the next tile in the queue FGTileEntry* tile = tile_free_queue.front(); tile_free_queue.pop(); @@ -174,7 +176,7 @@ FGTileLoader::LoaderThread::run() #ifdef WISH_PLIB_WAS_THREADED // but it isn't // Handle and pending removals while ( !loader->tile_free_queue.empty() ) { - cout << "freeing next tile ..." << endl; + // cout << "freeing next tile ..." << endl; // free the next tile in the queue FGTileEntry* tile = loader->tile_free_queue.pop(); tile->free_tile(); diff --git a/src/Scenery/FGTileLoader.hxx b/src/Scenery/FGTileLoader.hxx index 91ecb82df..78334b5ea 100644 --- a/src/Scenery/FGTileLoader.hxx +++ b/src/Scenery/FGTileLoader.hxx @@ -54,12 +54,14 @@ public: */ ~FGTileLoader(); +#if 0 // we don't ever want to do this I don't think /** * Flush anything in pending load queue without doing the work * Leave the free queue intact since that's are only record of * things we need to remove. */ void reinit(); +#endif /** * Add a tile to the end of the load queue. diff --git a/src/Scenery/newcache.cxx b/src/Scenery/newcache.cxx index 841fb4bac..a93c93677 100644 --- a/src/Scenery/newcache.cxx +++ b/src/Scenery/newcache.cxx @@ -49,7 +49,9 @@ SG_USING_NAMESPACE(std); // Constructor -FGNewCache::FGNewCache( void ) { +FGNewCache::FGNewCache( void ) : + max_cache_size(50) +{ tile_cache.clear(); } @@ -78,32 +80,16 @@ void FGNewCache::entry_free( long cache_index ) { // Initialize the tile cache subsystem void FGNewCache::init( void ) { - // This is a hack that should really get cleaned up at some point - extern ssgBranch *terrain; - SG_LOG( SG_TERRAIN, SG_INFO, "Initializing the tile cache." ); - // expand cache if needed. For best results ... i.e. to avoid - // tile load problems and blank areas: - max_cache_size = 50; // a random number to start with SG_LOG( SG_TERRAIN, SG_INFO, " max cache size = " << max_cache_size ); SG_LOG( SG_TERRAIN, SG_INFO, " current cache size = " << tile_cache.size() ); - - tile_map_iterator current = tile_cache.begin(); - tile_map_iterator end = tile_cache.end(); - - for ( ; current != end; ++current ) { - long index = current->first; - SG_LOG( SG_TERRAIN, SG_DEBUG, "clearing " << index ); - FGTileEntry *e = current->second; - e->tile_bucket.make_bad(); - entry_free(index); - } - // and ... just in case we missed something ... - terrain->removeAllKids(); +#if 0 // don't clear the cache right now + clear_cache(); +#endif SG_LOG( SG_TERRAIN, SG_INFO, " done with init()" ); } @@ -208,13 +194,37 @@ void FGNewCache::make_space() { SG_LOG( SG_TERRAIN, SG_DEBUG, " index = " << max_index ); entry_free( max_index ); } else { - SG_LOG( SG_TERRAIN, SG_ALERT, "WHOOPS!!! Dying in next_avail()" ); + SG_LOG( SG_TERRAIN, SG_ALERT, "WHOOPS!!! Dying in make_space()" + "tile cache is full, but no entries available to removal."); exit( -1 ); } } } +// Clear all completely loaded tiles (ignores partially loaded tiles) +void FGNewCache::clear_cache() { + // This is a hack that should really get cleaned up at some point + extern ssgBranch *terrain; + + tile_map_iterator current = tile_cache.begin(); + tile_map_iterator end = tile_cache.end(); + + for ( ; current != end; ++current ) { + long index = current->first; + SG_LOG( SG_TERRAIN, SG_DEBUG, "clearing " << index ); + FGTileEntry *e = current->second; + if ( e->is_loaded() && e->get_pending_models() == 0 ) { + e->tile_bucket.make_bad(); + entry_free(index); + } + } + + // and ... just in case we missed something ... + terrain->removeAllKids(); +} + + /** * Create a new tile and schedule it for loading. */ diff --git a/src/Scenery/newcache.hxx b/src/Scenery/newcache.hxx index 38dbc71ca..91b43c6ba 100644 --- a/src/Scenery/newcache.hxx +++ b/src/Scenery/newcache.hxx @@ -85,6 +85,9 @@ public: // Ensure at least one entry is free in the cache void make_space(); + // Clear all completely loaded tiles (ignores partially loaded tiles) + void clear_cache(); + // Fill in a tile cache entry with real data for the specified bucket // void fill_in( const SGBucket& b ); diff --git a/src/Scenery/tileentry.cxx b/src/Scenery/tileentry.cxx index cfc7b100a..a7d8f8195 100644 --- a/src/Scenery/tileentry.cxx +++ b/src/Scenery/tileentry.cxx @@ -577,6 +577,12 @@ FGTileEntry::add_ssg_nodes( ssgBranch* terrain, ssgBranch* ground ) terra_transform->ref(); terrain->addKid( terra_transform ); + SG_LOG( SG_TERRAIN, SG_DEBUG, + "connected a tile into scene graph. terra_transform = " + << terra_transform ); + SG_LOG( SG_TERRAIN, SG_DEBUG, "num parents now = " + << terra_transform->getNumParents() ); + if ( lights_transform != 0 ) { // bump up the ref count so we can remove this later without // having ssg try to free the memory. @@ -591,8 +597,14 @@ FGTileEntry::add_ssg_nodes( ssgBranch* terrain, ssgBranch* ground ) void FGTileEntry::disconnect_ssg_nodes() { - cout << "disconnecting ssg nodes" << endl; + SG_LOG( SG_TERRAIN, SG_INFO, "disconnecting ssg nodes" ); + if ( ! loaded ) { + SG_LOG( SG_TERRAIN, SG_INFO, "removing a not-fully loaded tile!" ); + } else { + SG_LOG( SG_TERRAIN, SG_INFO, "removing a fully loaded tile! terra_transform = " << terra_transform ); + } + // find the terrain branch parent int pcount = terra_transform->getNumParents(); if ( pcount > 0 ) { diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index 777110498..fbf44325c 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -97,7 +97,13 @@ int FGTileMgr::init() { SG_LOG( SG_TERRAIN, SG_INFO, "Initializing Tile Manager subsystem." ); tile_cache.init(); - destroy_queue(); + +#if 0 + + // instead it's just a lot easier to let any pending work flush + // through, rather than trying to arrest the queue and nuke all + // the various work at all the various stages and get everything + // cleaned up properly. while ( ! attach_queue.empty() ) { attach_queue.pop(); @@ -113,17 +119,6 @@ int FGTileMgr::init() { delete dm; } loader.reinit(); - -#if 0 - if ( state != Start ) { - SG_LOG( SG_TERRAIN, SG_INFO, - "... Reinitializing." ); - destroy_queue(); - } else { - SG_LOG( SG_TERRAIN, SG_INFO, - "... First time through." ); - tile_cache.init(); - } #endif hit_list.clear(); @@ -318,15 +313,6 @@ void FGTileMgr::initialize_queue() } -// forced emptying of the queue -// This is necessay to keep bookeeping straight for the -// tile_cache -- which actually handles all the -// (de)allocations -void FGTileMgr::destroy_queue() { - // load_queue.clear(); -} - - // given the current lon/lat (in degrees), fill in the array of local // chunks. If the chunk isn't already in the cache, then read it from // disk. diff --git a/src/Scenery/tilemgr.hxx b/src/Scenery/tilemgr.hxx index b4ae8ac1d..a6cfeb5b7 100644 --- a/src/Scenery/tilemgr.hxx +++ b/src/Scenery/tilemgr.hxx @@ -72,11 +72,6 @@ private: // initialize the cache void initialize_queue(); - // forced emptying of the queue. This is necessay to keep - // bookeeping straight for the tile_cache -- which actually - // handles all the (de)allocations - void destroy_queue(); - // schedule a tile for loading void sched_tile( const SGBucket& b ); -- 2.39.5