STL portability, tons o' stuff. :-)
Currently trying to get a BeOS port together but life keeps getting
in the way!
+ Threading support and threaded tile pager.
Bernhard H. Buckel <buckel@mail.uni-wuerzburg.de>
#include <Main/globals.hxx>
#include "FGTileLoader.hxx"
#include "tileentry.hxx"
+#include "tilemgr.hxx"
/**
*
{
#ifdef ENABLE_THREADS
// Wake up its time to die.
- queue_cond.broadcast();
+ // queue_cond.broadcast();
for (int i = 0; i < MAX_THREADS; ++i)
{
}
#ifdef ENABLE_THREADS
- mutex.lock();
tile_queue.push( tile );
- // Signal waiting working threads.
- queue_cond.signal();
- mutex.unlock();
#else
tile->load( tile_path, true );
#endif // ENABLE_THREADS
pthread_cleanup_push( cleanup_handler, loader );
while ( true ) {
// Wait for a load request to be placed in the queue.
- loader->mutex.lock();
- while (loader->empty())
- {
- loader->queue_cond.wait( loader->mutex );
- }
-
- // Have we been canceled - exits if yes.
- //pthread_testcancel();
- if (loader->empty())
- {
- loader->mutex.unlock();
- pthread_exit( PTHREAD_CANCELED );
- }
+ FGTileEntry* tile = loader->tile_queue.pop();
// 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();
- loader->mutex.unlock();
+ // loader->mutex.lock();
+ // loader->frame_cond.wait( loader->mutex );
+ // loader->mutex.unlock();
set_cancel( SGThread::CANCEL_DISABLE );
tile->load( loader->tile_path, true );
set_cancel( SGThread::CANCEL_DEFERRED );
+
+ FGTileMgr::loaded( tile );
}
pthread_cleanup_pop(1);
}
#ifndef FG_TILE_LOADER_HXX
#define FG_TILE_LOADER_HXX
-#include <queue>
-#include <pthread.h>
-
#include <simgear/bucket/newbucket.hxx>
#include <simgear/misc/sg_path.hxx>
#ifdef ENABLE_THREADS
# include <simgear/threads/SGThread.hxx>
+# include <simgear/threads/SGQueue.hxx>
#endif
// Forward reference.
* Returns whether the load queue is empty (contains no elements).
* @return true if load queue is empty otherwise returns false.
*/
- bool empty() const { return tile_queue.empty(); }
+ // bool empty() const { return tile_queue.empty(); }
private:
/**
* FIFO queue of tiles to load from data files.
*/
- std::queue< FGTileEntry* > tile_queue;
-
+ SGBlockingQueue< FGTileEntry* > tile_queue;
+
/**
* Base name of directory containing tile data file.
*/
* Lock and synchronize access to tile queue.
*/
SGMutex mutex;
- SGCondition queue_cond;
SGCondition frame_cond;
/**
// ssg as well as the whole ssg branch
void FGTileEntry::free_tile() {
int i;
- SG_LOG( SG_TERRAIN, SG_DEBUG,
+ SG_LOG( SG_TERRAIN, SG_INFO,
"FREEING TILE = (" << tile_bucket << ")" );
SG_LOG( SG_TERRAIN, SG_DEBUG,
<< " texture coordinate arrays" );
for ( i = 0; i < (int)vec3_ptrs.size(); ++i ) {
- delete [] vec3_ptrs[i]; //that's the correct version
+ delete [] vec3_ptrs[i];
}
vec3_ptrs.clear();
for ( i = 0; i < (int)vec2_ptrs.size(); ++i ) {
- delete [] vec2_ptrs[i]; //that's the correct version
+ delete [] vec2_ptrs[i];
}
vec2_ptrs.clear();
void
FGTileEntry::load( const SGPath& base, bool is_base )
{
- // a cheesy hack (to be fixed later)
- extern ssgBranch *terrain;
- extern ssgBranch *ground;
-
string index_str = tile_bucket.gen_index_str();
SGPath tile_path = base;
basename.append( index_str );
string path = basename.str();
- SG_LOG( SG_TERRAIN, SG_DEBUG, "Loading tile " << path );
+ SG_LOG( SG_TERRAIN, SG_INFO, "Loading tile " << path );
// fgObjLoad will generate ground lighting for us ...
ssgVertexArray *light_pts = new ssgVertexArray( 100 );
offset.x(), offset.y(), offset.z(),
0.0, 0.0, 0.0 );
terra_transform->setTransform( &sgcoord );
- terrain->addKid( terra_transform );
+ // terrain->addKid( terra_transform );
lights_transform = NULL;
lights_range = NULL;
lights_range->addKid( lights_brightness );
lights_transform->addKid( lights_range );
lights_transform->setTransform( &sgcoord );
- ground->addKid( lights_transform );
+ // ground->addKid( lights_transform );
}
/* end of ground light section */
+}
+
+void
+FGTileEntry::add_ssg_nodes( ssgBranch* terrain, ssgBranch* ground )
+{
+ terrain->addKid( terra_transform );
+ if (lights_transform != 0)
+ ground->addKid( lights_transform );
loaded = true;
}
ssgSelector *lights_brightness;
/**
- * Indicates this tile has been loaded from a file.
- * Note that this may be set asynchronously by another thread.
+ * Indicates this tile has been loaded from a file and connected
+ * into the scene graph. Note that this may be set asynchronously
+ * by another thread.
*/
volatile bool loaded;
*/
inline SGBucket get_tile_bucket() const { return tile_bucket; }
+ /**
+ * Add terrain mesh and ground lighting to scene graph.
+ */
+ void add_ssg_nodes( ssgBranch* terrain, ssgBranch* ground );
};
extern ssgRoot *scene;
extern ssgBranch *terrain;
+extern ssgBranch *ground;
// the tile manager
FGTileMgr global_tile_mgr;
return Point3D(a.x()+b[0], a.y()+b[1], a.z()+b[2]);
}
+#ifdef ENABLE_THREADS
+SGLockedQueue<FGTileEntry*> FGTileMgr::loaded_queue;
+#endif // ENABLE_THREADS
// Constructor
FGTileMgr::FGTileMgr():
state( Start ),
- vis( 16000 )
+ vis( 16000 ),
+ counter_hack(0)
{
}
counter_hack = (counter_hack + 1) % 5;
if ( !counter_hack ) {
// Notify the tile loader that it can load another tile
- loader.update();
+ // loader.update();
+
+#ifdef ENABLE_THREADS
+ if (!loaded_queue.empty())
+ {
+ FGTileEntry* e = loaded_queue.pop();
+ e->add_ssg_nodes( terrain, ground );
+ //std::cout << "Adding ssg nodes for "
+ //<< e->get_tile_bucket() << "\n";
+ }
+#endif // ENABLE_THREADS
}
return 1;
#include <plib/ssg.h>
#include <simgear/bucket/newbucket.hxx>
+#ifdef ENABLE_THREADS
+# include <simgear/threads/SGQueue.hxx>
+#endif // ENABLE_THREADS
#include "FGTileLoader.hxx"
#include "hitlist.hxx"
FGTileLoader loader;
int counter_hack;
+#ifdef ENABLE_THREADS
+ /**
+ * Tiles to add to scene graph.
+ */
+ static SGLockedQueue<FGTileEntry*> loaded_queue;
+
+public:
+
+ /**
+ * Add a loaded tile to the scene graph queue.
+ */
+ static void loaded( FGTileEntry* t ) { loaded_queue.push(t); }
+#endif // ENABLE_THREADS
+
public:
// Constructor