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:
parent
f117bc201f
commit
a29cb28e93
7 changed files with 65 additions and 24 deletions
|
@ -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();
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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 );
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue