From d683d39e8552be5fadedd996c648dd7e16af17ee Mon Sep 17 00:00:00 2001
From: ThorstenB <brehmt@gmail.com>
Date: Sun, 15 Apr 2012 15:30:44 +0200
Subject: [PATCH] Fix SceneryPager destruction sequence. SceneryPager singleton
 must not be removed while FGScenery is still alive, so hold a reference to it
 in FGScenery, saving the pager from being deleted first.

---
 src/AIModel/AIBase.cxx  |  2 +-
 src/Scenery/scenery.cxx |  4 +++-
 src/Scenery/scenery.hxx | 10 ++++++----
 src/Scenery/tilemgr.cxx | 18 +++++++++---------
 src/Scenery/tilemgr.hxx |  5 ++++-
 5 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/src/AIModel/AIBase.cxx b/src/AIModel/AIBase.cxx
index 44494dc54..0945a13e6 100644
--- a/src/AIModel/AIBase.cxx
+++ b/src/AIModel/AIBase.cxx
@@ -175,7 +175,7 @@ FGAIBase::removeModel()
         aip.init( 0 );
         _model = 0;
         // pass it on to the pager, to be be deleted in the pager thread
-        pSceneryManager->getPagerSingleton()->queueDeleteRequest(temp);
+        pSceneryManager->getPager()->queueDeleteRequest(temp);
     }
     else
     {
diff --git a/src/Scenery/scenery.cxx b/src/Scenery/scenery.cxx
index 12c3ebb69..908f4da22 100644
--- a/src/Scenery/scenery.cxx
+++ b/src/Scenery/scenery.cxx
@@ -212,6 +212,8 @@ private:
 FGScenery::FGScenery()
 {
     SG_LOG( SG_TERRAIN, SG_INFO, "Initializing scenery subsystem" );
+    // keep reference to pager singleton, so it cannot be destroyed while FGScenery lives
+    _pager = FGScenery::getPagerSingleton();
 }
 
 FGScenery::~FGScenery() {
@@ -327,7 +329,7 @@ bool FGScenery::scenery_available(const SGGeod& position, double range_m)
     SGVec3f p = SGVec3f::fromGeod(SGGeod::fromGeodM(position, elev));
     osg::FrameStamp* framestamp
             = globals->get_renderer()->getViewer()->getFrameStamp();
-    simgear::CheckSceneryVisitor csnv(getPagerSingleton(), toOsg(p), range_m, framestamp);
+    simgear::CheckSceneryVisitor csnv(_pager, toOsg(p), range_m, framestamp);
     // currently the PagedLODs will not be loaded by the DatabasePager
     // while the splashscreen is there, so CheckSceneryVisitor force-loads
     // missing objects in the main thread
diff --git a/src/Scenery/scenery.hxx b/src/Scenery/scenery.hxx
index bd976ba23..b83b8adb9 100644
--- a/src/Scenery/scenery.hxx
+++ b/src/Scenery/scenery.hxx
@@ -48,6 +48,7 @@ class FGScenery : public SGSubsystem {
     osg::ref_ptr<osg::Group> terrain_branch;
     osg::ref_ptr<osg::Group> models_branch;
     osg::ref_ptr<osg::Group> aircraft_branch;
+    osg::ref_ptr<flightgear::SceneryPager> _pager;
 
 public:
 
@@ -74,9 +75,9 @@ public:
                          const SGMaterial** material,
                          const osg::Node* butNotFrom = 0);
 
-    /// Compute the elevation of the scenery beow the cartesian point pos.
+    /// Compute the elevation of the scenery below the cartesian point pos.
     /// you the returned scenery altitude is not higher than the position
-    /// pos plus an ofset given with max_altoff.
+    /// pos plus an offset given with max_altoff.
     /// If the exact flag is set to true, the scenery center is moved to
     /// gain a higher accuracy of that query. The center is restored past
     /// that to the original value.
@@ -92,7 +93,7 @@ public:
     /// Compute the nearest intersection point of the line starting from 
     /// start going in direction dir with the terrain.
     /// The input and output values should be in cartesian coordinates in the
-    /// usual earth centered wgs84 coordiante system. Units are meters.
+    /// usual earth centered wgs84 coordinate system. Units are meters.
     /// On success, true is returned.
     bool get_cart_ground_intersection(const SGVec3d& start, const SGVec3d& dir,
                                       SGVec3d& nearestHit,
@@ -103,7 +104,7 @@ public:
     osg::Group *get_models_branch () const { return models_branch.get(); }
     osg::Group *get_aircraft_branch () const { return aircraft_branch.get(); }
 
-    /// Returns true if scenery is avaliable for the given lat, lon position
+    /// Returns true if scenery is available for the given lat, lon position
     /// within a range of range_m.
     /// lat and lon are expected to be in degrees.
     bool scenery_available(const SGGeod& position, double range_m);
@@ -111,6 +112,7 @@ public:
     // Static because access to the pager is needed before the rest of
     // the scenery is initialized.
     static flightgear::SceneryPager* getPagerSingleton();
+    flightgear::SceneryPager* getPager() { return _pager.get(); }
 };
 
 
diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx
index 0f566485b..347131655 100644
--- a/src/Scenery/tilemgr.cxx
+++ b/src/Scenery/tilemgr.cxx
@@ -60,7 +60,8 @@ FGTileMgr::FGTileMgr():
     _terra_sync(NULL),
     _visibilityMeters(fgGetNode("/environment/visibility-m", true)),
     _maxTileRangeM(fgGetNode("/sim/rendering/static-lod/bare", true)),
-    _disableNasalHooks(fgGetNode("/sim/temp/disable-scenery-nasal", true))
+    _disableNasalHooks(fgGetNode("/sim/temp/disable-scenery-nasal", true)),
+    _pager(FGScenery::getPagerSingleton())
 {
 }
 
@@ -233,7 +234,6 @@ void FGTileMgr::schedule_needed(const SGBucket& curr_bucket, double vis)
  */
 void FGTileMgr::update_queues()
 {
-    SceneryPager* pager = FGScenery::getPagerSingleton();
     osg::FrameStamp* framestamp
         = globals->get_renderer()->getViewer()->getFrameStamp();
     double current_time = framestamp->getReferenceTime();
@@ -261,12 +261,12 @@ void FGTileMgr::update_queues()
                   e->is_current_view() ))
             {
                 // schedule tile for loading with osg pager
-                pager->queueRequest(e->tileFileName,
-                                    e->getNode(),
-                                    e->get_priority(),
-                                    framestamp,
-                                    e->getDatabaseRequest(),
-                                    _options.get());
+                _pager->queueRequest(e->tileFileName,
+                                     e->getNode(),
+                                     e->get_priority(),
+                                     framestamp,
+                                     e->getDatabaseRequest(),
+                                     _options.get());
                 loading++;
             }
         } else
@@ -293,7 +293,7 @@ void FGTileMgr::update_queues()
             delete old;
             // zeros out subgraph ref_ptr, so subgraph is owned by
             // the pager and will be deleted in the pager thread.
-            pager->queueDeleteRequest(subgraph);
+            _pager->queueDeleteRequest(subgraph);
             
             if (--drop_count > 0)
                 drop_index = tile_cache.get_drop_tile();
diff --git a/src/Scenery/tilemgr.hxx b/src/Scenery/tilemgr.hxx
index 241e40396..9f9473d1a 100644
--- a/src/Scenery/tilemgr.hxx
+++ b/src/Scenery/tilemgr.hxx
@@ -28,6 +28,7 @@
 
 #include <simgear/structure/subsystem_mgr.hxx>
 #include <simgear/bucket/newbucket.hxx>
+#include "SceneryPager.hxx"
 #include "tileentry.hxx"
 #include "tilecache.hxx"
 
@@ -85,7 +86,9 @@ private:
 
     SGPropertyNode_ptr _visibilityMeters;
     SGPropertyNode_ptr _maxTileRangeM, _disableNasalHooks;
-    
+
+    osg::ref_ptr<flightgear::SceneryPager> _pager;
+
 public:
     FGTileMgr();