1
0
Fork 0

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.
This commit is contained in:
curt 2001-05-30 18:21:03 +00:00
parent 5893de13ff
commit d5a2533411
7 changed files with 61 additions and 51 deletions

View 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(); tile_load_queue.pop();
} }
} }
#endif
/** /**
@ -125,7 +127,7 @@ FGTileLoader::update()
mutex.unlock(); mutex.unlock();
#else #else
if ( !tile_load_queue.empty() ) { if ( !tile_load_queue.empty() ) {
cout << "loading next tile ..." << endl; // cout << "loading next tile ..." << endl;
// load the next tile in the queue // load the next tile in the queue
FGTileEntry* tile = tile_load_queue.front(); FGTileEntry* tile = tile_load_queue.front();
tile_load_queue.pop(); tile_load_queue.pop();
@ -135,7 +137,7 @@ FGTileLoader::update()
#ifdef WISH_PLIB_WAS_THREADED // but it isn't #ifdef WISH_PLIB_WAS_THREADED // but it isn't
if ( !tile_free_queue.empty() ) { if ( !tile_free_queue.empty() ) {
cout << "freeing next tile ..." << endl; // cout << "freeing next tile ..." << endl;
// free the next tile in the queue // free the next tile in the queue
FGTileEntry* tile = tile_free_queue.front(); FGTileEntry* tile = tile_free_queue.front();
tile_free_queue.pop(); tile_free_queue.pop();
@ -174,7 +176,7 @@ FGTileLoader::LoaderThread::run()
#ifdef WISH_PLIB_WAS_THREADED // but it isn't #ifdef WISH_PLIB_WAS_THREADED // but it isn't
// Handle and pending removals // Handle and pending removals
while ( !loader->tile_free_queue.empty() ) { while ( !loader->tile_free_queue.empty() ) {
cout << "freeing next tile ..." << endl; // cout << "freeing next tile ..." << endl;
// free the next tile in the queue // free the next tile in the queue
FGTileEntry* tile = loader->tile_free_queue.pop(); FGTileEntry* tile = loader->tile_free_queue.pop();
tile->free_tile(); tile->free_tile();

View file

@ -54,12 +54,14 @@ public:
*/ */
~FGTileLoader(); ~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 * Flush anything in pending load queue without doing the work
* Leave the free queue intact since that's are only record of * Leave the free queue intact since that's are only record of
* things we need to remove. * things we need to remove.
*/ */
void reinit(); void reinit();
#endif
/** /**
* Add a tile to the end of the load queue. * Add a tile to the end of the load queue.

View file

@ -49,7 +49,9 @@ SG_USING_NAMESPACE(std);
// Constructor // Constructor
FGNewCache::FGNewCache( void ) { FGNewCache::FGNewCache( void ) :
max_cache_size(50)
{
tile_cache.clear(); tile_cache.clear();
} }
@ -78,32 +80,16 @@ void FGNewCache::entry_free( long cache_index ) {
// Initialize the tile cache subsystem // Initialize the tile cache subsystem
void FGNewCache::init( void ) { 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." ); 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 = " SG_LOG( SG_TERRAIN, SG_INFO, " max cache size = "
<< max_cache_size ); << max_cache_size );
SG_LOG( SG_TERRAIN, SG_INFO, " current cache size = " SG_LOG( SG_TERRAIN, SG_INFO, " current cache size = "
<< tile_cache.size() ); << tile_cache.size() );
tile_map_iterator current = tile_cache.begin(); #if 0 // don't clear the cache right now
tile_map_iterator end = tile_cache.end(); clear_cache();
#endif
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();
SG_LOG( SG_TERRAIN, SG_INFO, " done with init()" ); 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 ); SG_LOG( SG_TERRAIN, SG_DEBUG, " index = " << max_index );
entry_free( max_index ); entry_free( max_index );
} else { } 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 ); 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. * Create a new tile and schedule it for loading.
*/ */

View file

@ -85,6 +85,9 @@ public:
// Ensure at least one entry is free in the cache // Ensure at least one entry is free in the cache
void make_space(); 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 // Fill in a tile cache entry with real data for the specified bucket
// void fill_in( const SGBucket& b ); // void fill_in( const SGBucket& b );

View file

@ -577,6 +577,12 @@ FGTileEntry::add_ssg_nodes( ssgBranch* terrain, ssgBranch* ground )
terra_transform->ref(); terra_transform->ref();
terrain->addKid( terra_transform ); 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 ) { if ( lights_transform != 0 ) {
// bump up the ref count so we can remove this later without // bump up the ref count so we can remove this later without
// having ssg try to free the memory. // having ssg try to free the memory.
@ -591,7 +597,13 @@ FGTileEntry::add_ssg_nodes( ssgBranch* terrain, ssgBranch* ground )
void void
FGTileEntry::disconnect_ssg_nodes() 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 // find the terrain branch parent
int pcount = terra_transform->getNumParents(); int pcount = terra_transform->getNumParents();

View file

@ -97,7 +97,13 @@ int FGTileMgr::init() {
SG_LOG( SG_TERRAIN, SG_INFO, "Initializing Tile Manager subsystem." ); SG_LOG( SG_TERRAIN, SG_INFO, "Initializing Tile Manager subsystem." );
tile_cache.init(); 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() ) { while ( ! attach_queue.empty() ) {
attach_queue.pop(); attach_queue.pop();
@ -113,17 +119,6 @@ int FGTileMgr::init() {
delete dm; delete dm;
} }
loader.reinit(); 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 #endif
hit_list.clear(); 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 // 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 // chunks. If the chunk isn't already in the cache, then read it from
// disk. // disk.

View file

@ -72,11 +72,6 @@ private:
// initialize the cache // initialize the cache
void initialize_queue(); 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 // schedule a tile for loading
void sched_tile( const SGBucket& b ); void sched_tile( const SGBucket& b );