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
// Wake up its time to die.
cond.broadcast();
queue_cond.broadcast();
for (int i = 0; i < MAX_THREADS; ++i)
{
@ -86,13 +86,27 @@ FGTileLoader::add( FGTileEntry* tile )
mutex.lock();
tile_queue.push( tile );
// Signal waiting working threads.
cond.signal();
queue_cond.signal();
mutex.unlock();
#else
tile->load( tile_path, true );
#endif // ENABLE_THREADS
}
/**
*
*/
void
FGTileLoader::update()
{
#ifdef ENABLE_THREADS
mutex.lock();
frame_cond.signal();
mutex.unlock();
#endif // ENABLE_THREADS
}
#ifdef ENABLE_THREADS
/**
*
@ -106,7 +120,7 @@ FGTileLoader::LoaderThread::run()
loader->mutex.lock();
while (loader->empty())
{
loader->cond.wait( loader->mutex );
loader->queue_cond.wait( loader->mutex );
}
// Have we been canceled - exits if yes.
@ -117,6 +131,10 @@ FGTileLoader::LoaderThread::run()
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.
FGTileEntry* tile = loader->tile_queue.front();
loader->tile_queue.pop();

View file

@ -61,6 +61,14 @@ public:
*/
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).
* @return true if load queue is empty otherwise returns false.
@ -123,7 +131,8 @@ private:
* Lock and synchronize access to tile queue.
*/
SGMutex mutex;
SGCondition cond;
SGCondition queue_cond;
SGCondition frame_cond;
/**
* Thread cleanup handler.

View file

@ -212,18 +212,13 @@ void FGNewCache::make_space() {
* Create a new tile and schedule it for loading.
*/
void
FGNewCache::load_tile( const SGBucket& b )
FGNewCache::insert_tile( FGTileEntry *e )
{
// clear out a distant entry in the cache if needed.
make_space();
// create the entry
FGTileEntry *e = new FGTileEntry( b );
// 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;
// Schedule tile for loading
loader.add( e );
}

View file

@ -46,7 +46,6 @@
#include <simgear/math/point3d.hxx>
#include "tileentry.hxx"
#include "FGTileLoader.hxx"
SG_USING_STD(map);
@ -69,11 +68,6 @@ class FGNewCache {
// Free a tile cache entry
void entry_free( long cache_index );
/**
* Queue tiles for loading.
*/
FGTileLoader loader;
public:
// Constructor
@ -128,7 +122,7 @@ public:
* Create a new tile and enqueue it for loading.
* @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
* 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 );
if ( t == NULL ) {
// register a load request
tile_cache.load_tile( b );
// create a new entry
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 );
// cout << "tile cache size = " << tile_cache.get_size() << endl;
int i;
// wipe/initialize tile cache
// tile_cache.init();
previous_bucket.make_bad();
@ -288,6 +292,7 @@ void FGTileMgr::initialize_queue()
#if 0
// Now force a load of the center tile and inner ring so we
// have something to see in our first frame.
int i;
for ( i = 0; i < 9; ++i ) {
if ( load_queue.size() ) {
SG_LOG( SG_TERRAIN, SG_DEBUG,
@ -402,6 +407,13 @@ int FGTileMgr::update( double lon, double lat ) {
last_longitude = longitude;
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;
}

View file

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