Improvements to the DatabasePager and PagedLOD class adding support for

deleting expuired children in the database thread.
This commit is contained in:
Robert Osfield 2003-07-09 14:55:39 +00:00
parent dcbaf59753
commit 5aa47a77c2
9 changed files with 140 additions and 50 deletions

View File

@ -19,6 +19,8 @@
namespace osg {
typedef std::vector< ref_ptr<Node> > NodeList;
/** General group node which maintains a list of children.
Children are reference counted. This allows children to be shared
with memory management handled automatically via osg::Referenced.
@ -27,7 +29,6 @@ class SG_EXPORT Group : public Node
{
public :
typedef std::vector<ref_ptr<Node> > ChildList;
Group();
@ -89,7 +90,7 @@ class SG_EXPORT Group : public Node
inline bool containsNode( const Node* node ) const
{
for (ChildList::const_iterator itr=_children.begin();
for (NodeList::const_iterator itr=_children.begin();
itr!=_children.end();
++itr)
{
@ -116,7 +117,7 @@ class SG_EXPORT Group : public Node
virtual bool computeBound() const;
ChildList _children;
NodeList _children;
};

View File

@ -74,7 +74,10 @@ class SG_EXPORT PagedLOD : public LOD
/** return the list of time stamps.*/
inline const TimeStampList& getTimeStampList() const { return _timeStampList; }
void removeExpiredChildren(double expiryTime);
/** Remove the children from the PagedLOD which haven't be visited since specified expiry time.
The removed children are added the removeChildren list passed into the method,
this allows the children to be deleted later at the callers discression.*/
void removeExpiredChildren(double expiryTime,NodeList& removedChildren);
protected :

View File

@ -33,19 +33,23 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques
DatabasePager();
/** add a request to load a node file to end the the database request list.*/
/** Add a request to load a node file to end the the database request list.*/
virtual void requestNodeFile(const std::string& fileName,osg::Group* group);
/** run does the database paging.*/
virtual void run();
/** add the loaded data to the scene graph.*/
/** Add the loaded data to the scene graph.*/
void addLoadedDataToSceneGraph();
/** find all PagedLOD nodes in a subgraph and register them with
* the DatabasePager so it can keep track of expired nodes.*/
/** Find all PagedLOD nodes in a subgraph and register them with
* the DatabasePager so it can keep track of expired nodes.
* note, should be only be called from the update thread. */
void registerPagedLODs(osg::Node* subgraph);
/** Set the amount of time that a subgraph will be kept without being visited in the cull traversal
* before being removed.*/
void setExpiryDelay(double expiryDelay) { _expiryDelay = expiryDelay; }
@ -54,10 +58,27 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques
* before being removed.*/
double getExpiryDelay() const { return _expiryDelay; }
/** iterate through the active PagedLOD nodes children removing
* children which havn't been visited since specified expiryTime.*/
/** set whether the removed subgraphs should be deleted in the database thread or not.*/
void setDeleteRemovedSubgraphsInDatabaseThread(bool flag) { _deleteRemovedSubgraphsInDatabaseThread = flag; }
/** get whether the removed subgraphs should be deleted in the database thread or not.*/
bool getDeleteRemovedSubgraphsInDatabaseThread() const { return _deleteRemovedSubgraphsInDatabaseThread; }
/** Iterate through the active PagedLOD nodes children removing
* children which havn't been visited since specified expiryTime.
* note, should be only be called from the update thread. */
void removeExpiredSubgraphs(double currentFrameTime);
/* Set the maximum amount of time available for compile rendering objects. */
void setMaximumTimeForCompilingRenderingObjects(double time) { _maximumTimeForCompiling = time; }
/* Get the maximum amount of time available for compile rendering objects. */
double getMaximumTimeForCompilingRenderingObjects() const { return _maximumTimeForCompiling; }
/** Compile the rendering objects (display lists,texture objects, VBO's) on loaded subgraph.
* note, should only be called from the draw thread.*/
void compileRenderingObjects(osg::State& state);
public:
@ -66,6 +87,9 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques
protected :
virtual ~DatabasePager() {}
typedef std::vector< osg::ref_ptr<osg::StateSet> > StateSetList;
typedef std::vector< osg::ref_ptr<osg::Drawable> > DrawableList;
struct DatabaseRequest : public osg::Referenced
{
@ -84,13 +108,23 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques
DatabaseRequestList _fileRequestList;
Producer::Mutex _fileRequestListMutex;
DatabaseRequestList _fileLoadedList;
Producer::Mutex _fileLoadedListMutex;
DatabaseRequestList _dataLoadedList;
Producer::Mutex _dataLoadedListMutex;
bool _deleteRemovedSubgraphsInDatabaseThread;
osg::NodeList _childrenToDeleteList;
Producer::Mutex _childrenToDeleteListMutex;
DatabaseRequestList _dataToMergeList;
Producer::Mutex _dataToMergeMutex;
PagedLODList _pagedLODList;
double _expiryDelay;
double _maximumTimeForCompiling;
};
}

View File

@ -45,7 +45,7 @@ class OSGPRODUCER_EXPORT OsgSceneHandler : public Producer::Camera::SceneHandler
{
public:
virtual ~Callback() {}
virtual void operator()(OsgSceneHandler&, const Producer::Camera &) = 0;
virtual void operator()(OsgSceneHandler&, Producer::Camera &) = 0;
};
virtual void clear(Producer::Camera& camera)

View File

@ -31,7 +31,7 @@ Group::Group()
Group::Group(const Group& group,const CopyOp& copyop):
Node(group,copyop)
{
for(ChildList::const_iterator itr=group._children.begin();
for(NodeList::const_iterator itr=group._children.begin();
itr!=group._children.end();
++itr)
{
@ -43,7 +43,7 @@ Group::Group(const Group& group,const CopyOp& copyop):
Group::~Group()
{
// remove reference to this from children's parent lists.
for(ChildList::iterator itr=_children.begin();
for(NodeList::iterator itr=_children.begin();
itr!=_children.end();
++itr)
{
@ -55,7 +55,7 @@ Group::~Group()
void Group::traverse(NodeVisitor& nv)
{
for(ChildList::iterator itr=_children.begin();
for(NodeList::iterator itr=_children.begin();
itr!=_children.end();
++itr)
{
@ -298,7 +298,7 @@ bool Group::computeBound() const
BoundingBox bb;
bb.init();
ChildList::const_iterator itr;
NodeList::const_iterator itr;
for(itr=_children.begin();
itr!=_children.end();
++itr)

View File

@ -129,7 +129,7 @@ void PagedLOD::setTimeStamp(unsigned int childNo, double timeStamp)
_timeStampList[childNo] = timeStamp;
}
void PagedLOD::removeExpiredChildren(double expiryTime)
void PagedLOD::removeExpiredChildren(double expiryTime,NodeList& removedChildren)
{
for(unsigned int i=_children.size();i>0;)
{
@ -137,6 +137,7 @@ void PagedLOD::removeExpiredChildren(double expiryTime)
if (!_fileNameList[i].empty() && _timeStampList[i]<expiryTime)
{
//std::cout<<"Removing child "<<_children[i].get()<<std::endl;
removedChildren.push_back(_children[i]);
Group::removeChild(_children[i].get());
}
}

View File

@ -9,8 +9,13 @@ using namespace osgProducer;
DatabasePager::DatabasePager()
{
std::cout<<"Constructing DatabasePager()"<<std::endl;
//std::cout<<"Constructing DatabasePager()"<<std::endl;
_deleteRemovedSubgraphsInDatabaseThread = true;
_expiryDelay = 1.0;
_maximumTimeForCompiling = 0.005; // 5ms.
}
void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* group)
@ -19,10 +24,10 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou
// search to see if filename already exist in the file loaded list.
bool foundEntry = false;
_fileLoadedListMutex.lock();
_dataLoadedListMutex.lock();
for(DatabaseRequestList::iterator litr = _fileLoadedList.begin();
litr != _fileLoadedList.end() && !foundEntry;
for(DatabaseRequestList::iterator litr = _dataLoadedList.begin();
litr != _dataLoadedList.end() && !foundEntry;
++litr)
{
if ((*litr)->_fileName==fileName)
@ -32,7 +37,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou
}
}
_fileLoadedListMutex.unlock();
_dataLoadedListMutex.unlock();
if (!foundEntry)
{
@ -78,6 +83,23 @@ void DatabasePager::run()
while(true)
{
//
// delete any children if required.
//
if (_deleteRemovedSubgraphsInDatabaseThread)
{
_childrenToDeleteListMutex.lock();
if (!_childrenToDeleteList.empty())
{
std::cout<<"In DatabasePager thread deleting "<<_childrenToDeleteList.size()<<" subgraphs"<<std::endl;
_childrenToDeleteList.clear();
}
_childrenToDeleteListMutex.unlock();
}
//
// load any subgraphs that are required.
//
osg::ref_ptr<DatabaseRequest> databaseRequest;
// get the front of the file request list.
@ -97,11 +119,11 @@ void DatabasePager::run()
if (databaseRequest->_loadedModel.valid())
{
_fileLoadedListMutex.lock();
_dataLoadedListMutex.lock();
_fileLoadedList.push_back(databaseRequest);
_dataLoadedList.push_back(databaseRequest);
_fileLoadedListMutex.unlock();
_dataLoadedListMutex.unlock();
}
}
@ -121,10 +143,10 @@ void DatabasePager::addLoadedDataToSceneGraph()
{
DatabaseRequestList localFileLoadedList;
// get the dat for the _fileLoadedList, leaving it empty via a std::vector<>.swap.
_fileLoadedListMutex.lock();
localFileLoadedList.swap(_fileLoadedList);
_fileLoadedListMutex.unlock();
// get the dat for the _dataLoadedList, leaving it empty via a std::vector<>.swap.
_dataLoadedListMutex.lock();
localFileLoadedList.swap(_dataLoadedList);
_dataLoadedListMutex.unlock();
// add the loaded data into the scene graph.
for(DatabaseRequestList::iterator itr=localFileLoadedList.begin();
@ -144,13 +166,15 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
{
double expiryTime = currentFrameTime - _expiryDelay;
osg::NodeList childrenRemoved;
//std::cout<<"DatabasePager::removeExpiredSubgraphs("<<expiryTime<<") "<<std::endl;
for(PagedLODList::iterator itr=_pagedLODList.begin();
itr!=_pagedLODList.end();
++itr)
{
osg::PagedLOD* plod = itr->get();
plod->removeExpiredChildren(expiryTime);
plod->removeExpiredChildren(expiryTime,childrenRemoved);
}
for(unsigned int i=_pagedLODList.size();
@ -171,7 +195,14 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
}
}
if (_deleteRemovedSubgraphsInDatabaseThread)
{
// transfer the removed children over to the to delete list so the database thread can delete them.
_childrenToDeleteListMutex.lock();
_childrenToDeleteList.insert(_childrenToDeleteList.begin(),childrenRemoved.begin(),childrenRemoved.end());
_childrenToDeleteListMutex.unlock();
}
// otherwise the childrenRemoved list will automatically unref() and deleting the nodes.
}
@ -200,3 +231,8 @@ void DatabasePager::registerPagedLODs(osg::Node* subgraph)
if (subgraph) subgraph->accept(fplv);
}
void DatabasePager::compileRenderingObjects(osg::State& state)
{
// std::cout<<"Compiling rendering objects"<<std::endl;
}

View File

@ -413,24 +413,6 @@ bool OsgCameraGroup::realize()
}
if (sfsn._foundPagedLOD)
{
std::cout << "setting up paged LOD"<<std::endl;
_databasePager = new DatabasePager;
_databasePager->registerPagedLODs(getTopMostSceneData());
for(SceneHandlerList::iterator p=_shvec.begin();
p!=_shvec.end();
++p)
{
(*p)->getSceneView()->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get());
}
}
}

View File

@ -296,11 +296,44 @@ bool Viewer::realize( ThreadingModel thread_model )
return realize();
}
class DatabasePagerCompileCallback : public OsgSceneHandler::Callback
{
public:
DatabasePagerCompileCallback(DatabasePager* databasePager):
_databasePager(databasePager)
{}
virtual void operator()(OsgSceneHandler& sh, Producer::Camera& camera)
{
_databasePager->compileRenderingObjects(*(sh.getSceneView()->getState()));
sh.drawImplementation(camera);
}
osg::ref_ptr<DatabasePager> _databasePager;
};
bool Viewer::realize()
{
if (_realized) return _realized;
OsgCameraGroup::realize();
// by default set up the DatabasePager.
{
_databasePager = new DatabasePager;
_databasePager->registerPagedLODs(getTopMostSceneData());
for(SceneHandlerList::iterator p=_shvec.begin();
p!=_shvec.end();
++p)
{
(*p)->getSceneView()->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get());
(*p)->setDrawCallback(new DatabasePagerCompileCallback(_databasePager.get()));
}
}
// force a sync before we intialize the keyswitch manipulator to home
// so that Producer has a chance to set up the windows before we do