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:
parent
5893de13ff
commit
d5a2533411
7 changed files with 61 additions and 51 deletions
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue