]> git.mxchange.org Git - flightgear.git/commitdiff
Fixed a bug in the tile pager / caching / management system that caused
authorcurt <curt>
Wed, 30 May 2001 18:21:03 +0000 (18:21 +0000)
committercurt <curt>
Wed, 30 May 2001 18:21:03 +0000 (18:21 +0000)
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
src/Scenery/FGTileLoader.hxx
src/Scenery/newcache.cxx
src/Scenery/newcache.hxx
src/Scenery/tileentry.cxx
src/Scenery/tilemgr.cxx
src/Scenery/tilemgr.hxx

index a27d79dd769781a496b52115bb77c0e882eee7f4..69338c03b88d42df4b3ef2639f33f5769dcb2051 100644 (file)
@@ -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();
index 91ecb82df74b4913d4d97664399491665f5e5bbd..78334b5eaaeaed552bcc3b77a9c0f8c0bef55d7a 100644 (file)
@@ -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.
index 841fb4bac071b0cefe90a30ab4e972f7996b3da3..a93c9367755b65cbab29f631508581eba7eeb8ec 100644 (file)
@@ -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.
  */
index 38dbc71ca96fea8b7601340dca8298222f4ce252..91b43c6baa0d47e185c035b227ab56f7df196362 100644 (file)
@@ -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 );
 
index cfc7b100a29f5b96aa9c64ceb83795faf2a1bdbf..a7d8f819561622f09c666128203d24904c094099 100644 (file)
@@ -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 ) {
index 7771104981449a3727bec0c72e2b7d481bca2abb..fbf44325c399dff5d61f6f087be22336a9b40507 100644 (file)
@@ -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.
index b4ae8ac1d4d3e9be11e41415c53b066c4477b924..a6cfeb5b719280d9c34dff17abdd4b74b4bdde5e 100644 (file)
@@ -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 );