1
0
Fork 0

Tweaks to the tile pager so it waits for a signal from the main thread before

loading the next tile.  This allows the main thread to "pace" the tile loader
so it consumes fewer resources.
This commit is contained in:
curt 2001-04-14 03:11:39 +00:00
parent f117bc201f
commit a29cb28e93
7 changed files with 65 additions and 24 deletions

View file

@ -50,7 +50,7 @@ FGTileLoader::~FGTileLoader()
{ {
#ifdef ENABLE_THREADS #ifdef ENABLE_THREADS
// Wake up its time to die. // Wake up its time to die.
cond.broadcast(); queue_cond.broadcast();
for (int i = 0; i < MAX_THREADS; ++i) for (int i = 0; i < MAX_THREADS; ++i)
{ {
@ -86,13 +86,27 @@ FGTileLoader::add( FGTileEntry* tile )
mutex.lock(); mutex.lock();
tile_queue.push( tile ); tile_queue.push( tile );
// Signal waiting working threads. // Signal waiting working threads.
cond.signal(); queue_cond.signal();
mutex.unlock(); mutex.unlock();
#else #else
tile->load( tile_path, true ); tile->load( tile_path, true );
#endif // ENABLE_THREADS #endif // ENABLE_THREADS
} }
/**
*
*/
void
FGTileLoader::update()
{
#ifdef ENABLE_THREADS
mutex.lock();
frame_cond.signal();
mutex.unlock();
#endif // ENABLE_THREADS
}
#ifdef ENABLE_THREADS #ifdef ENABLE_THREADS
/** /**
* *
@ -106,7 +120,7 @@ FGTileLoader::LoaderThread::run()
loader->mutex.lock(); loader->mutex.lock();
while (loader->empty()) while (loader->empty())
{ {
loader->cond.wait( loader->mutex ); loader->queue_cond.wait( loader->mutex );
} }
// Have we been canceled - exits if yes. // Have we been canceled - exits if yes.
@ -117,6 +131,10 @@ FGTileLoader::LoaderThread::run()
pthread_exit( PTHREAD_CANCELED ); pthread_exit( PTHREAD_CANCELED );
} }
// Wait for the next frame signal before we load a tile from the queue
// Note that loader->mutex is already locked at this point.
loader->frame_cond.wait( loader->mutex );
// Grab the tile to load and release the mutex. // Grab the tile to load and release the mutex.
FGTileEntry* tile = loader->tile_queue.front(); FGTileEntry* tile = loader->tile_queue.front();
loader->tile_queue.pop(); loader->tile_queue.pop();

View file

@ -61,6 +61,14 @@ public:
*/ */
void add( FGTileEntry* tile ); void add( FGTileEntry* tile );
/**
* The tile loader thread will only load one tile per call to the
* update() method. This is a way to spread out the work of the
* tile loader and slow it down so it is less intrusive. For
* systems built without thead support this is a no-op.
*/
void update();
/** /**
* Returns whether the load queue is empty (contains no elements). * Returns whether the load queue is empty (contains no elements).
* @return true if load queue is empty otherwise returns false. * @return true if load queue is empty otherwise returns false.
@ -123,7 +131,8 @@ private:
* Lock and synchronize access to tile queue. * Lock and synchronize access to tile queue.
*/ */
SGMutex mutex; SGMutex mutex;
SGCondition cond; SGCondition queue_cond;
SGCondition frame_cond;
/** /**
* Thread cleanup handler. * Thread cleanup handler.

View file

@ -212,18 +212,13 @@ void FGNewCache::make_space() {
* Create a new tile and schedule it for loading. * Create a new tile and schedule it for loading.
*/ */
void void
FGNewCache::load_tile( const SGBucket& b ) FGNewCache::insert_tile( FGTileEntry *e )
{ {
// clear out a distant entry in the cache if needed. // clear out a distant entry in the cache if needed.
make_space(); make_space();
// create the entry
FGTileEntry *e = new FGTileEntry( b );
// register it in the cache // register it in the cache
long tile_index = b.gen_index(); long tile_index = e->get_tile_bucket().gen_index();
tile_cache[tile_index] = e; tile_cache[tile_index] = e;
// Schedule tile for loading
loader.add( e );
} }

View file

@ -46,7 +46,6 @@
#include <simgear/math/point3d.hxx> #include <simgear/math/point3d.hxx>
#include "tileentry.hxx" #include "tileentry.hxx"
#include "FGTileLoader.hxx"
SG_USING_STD(map); SG_USING_STD(map);
@ -69,11 +68,6 @@ class FGNewCache {
// Free a tile cache entry // Free a tile cache entry
void entry_free( long cache_index ); void entry_free( long cache_index );
/**
* Queue tiles for loading.
*/
FGTileLoader loader;
public: public:
// Constructor // Constructor
@ -128,7 +122,7 @@ public:
* Create a new tile and enqueue it for loading. * Create a new tile and enqueue it for loading.
* @param b * @param b
*/ */
void load_tile( const SGBucket& b ); void insert_tile( FGTileEntry* e );
}; };

View file

@ -165,7 +165,13 @@ public:
* Return true if the tile entry is loaded, otherwise return false * Return true if the tile entry is loaded, otherwise return false
* indicating that the loading thread is still working on this. * indicating that the loading thread is still working on this.
*/ */
inline bool is_loaded() const { return loaded; } inline bool is_loaded() const { return loaded; }
/**
* Return the "bucket" for this tile
*/
inline SGBucket get_tile_bucket() const { return tile_bucket; }
}; };

View file

@ -116,8 +116,14 @@ void FGTileMgr::sched_tile( const SGBucket& b ) {
FGTileEntry *t = tile_cache.get_tile( b ); FGTileEntry *t = tile_cache.get_tile( b );
if ( t == NULL ) { if ( t == NULL ) {
// register a load request // create a new entry
tile_cache.load_tile( b ); FGTileEntry *e = new FGTileEntry( b );
// insert the tile into the cache
tile_cache.insert_tile( e );
// Schedule tile for loading
loader.add( e );
} }
} }
@ -271,8 +277,6 @@ void FGTileMgr::initialize_queue()
SG_LOG( SG_TERRAIN, SG_INFO, "Updating Tile list for " << current_bucket ); SG_LOG( SG_TERRAIN, SG_INFO, "Updating Tile list for " << current_bucket );
// cout << "tile cache size = " << tile_cache.get_size() << endl; // cout << "tile cache size = " << tile_cache.get_size() << endl;
int i;
// wipe/initialize tile cache // wipe/initialize tile cache
// tile_cache.init(); // tile_cache.init();
previous_bucket.make_bad(); previous_bucket.make_bad();
@ -288,6 +292,7 @@ void FGTileMgr::initialize_queue()
#if 0 #if 0
// Now force a load of the center tile and inner ring so we // Now force a load of the center tile and inner ring so we
// have something to see in our first frame. // have something to see in our first frame.
int i;
for ( i = 0; i < 9; ++i ) { for ( i = 0; i < 9; ++i ) {
if ( load_queue.size() ) { if ( load_queue.size() ) {
SG_LOG( SG_TERRAIN, SG_DEBUG, SG_LOG( SG_TERRAIN, SG_DEBUG,
@ -402,6 +407,13 @@ int FGTileMgr::update( double lon, double lat ) {
last_longitude = longitude; last_longitude = longitude;
last_latitude = latitude; last_latitude = latitude;
// activate loader thread one out of every 5 frames
counter_hack = (counter_hack + 1) % 5;
if ( !counter_hack ) {
// Notify the tile loader that it can load another tile
loader.update();
}
return 1; return 1;
} }

View file

@ -35,6 +35,7 @@
#include <simgear/bucket/newbucket.hxx> #include <simgear/bucket/newbucket.hxx>
#include "FGTileLoader.hxx"
#include "hitlist.hxx" #include "hitlist.hxx"
#include "newcache.hxx" #include "newcache.hxx"
@ -102,10 +103,16 @@ private:
double last_latitude; double last_latitude;
/** /**
* * tile cache
*/ */
FGNewCache tile_cache; FGNewCache tile_cache;
/**
* Queue tiles for loading.
*/
FGTileLoader loader;
int counter_hack;
public: public:
// Constructor // Constructor