[osg][osgearth]osg的分页加载,代码和结构图
DatabasePager加载数据的过程:
多线程 使用DatabasePager加载数据的流程:
左侧的图框表示数据的检索和输入, 中间的白色框表示用于数据存储的内存空间,而右边的图框表示存储数据的输出。此外,蓝色图框表示可以在DatabaseThread线程中完成的工作, 而橙色图框表示由线程之外的函数完成的工作。
void DatabasePager::DatabaseThread::run()
{
OSG_INFO<<_name<<": DatabasePager::DatabaseThread::run"<<std::endl; bool firstTime = true; osg::ref_ptr<DatabasePager::ReadQueue> read_queue;
osg::ref_ptr<DatabasePager::ReadQueue> out_queue; switch(_mode)
{
case(HANDLE_ALL_REQUESTS):
read_queue = _pager->_fileRequestQueue;
break;
case(HANDLE_NON_HTTP):
read_queue = _pager->_fileRequestQueue;
out_queue = _pager->_httpRequestQueue;
break;
case(HANDLE_ONLY_HTTP):
read_queue = _pager->_httpRequestQueue;
break;
} do
{
_active = false; read_queue->block(); if (_done)
{
break;
} _active = true; OSG_INFO<<_name<<": _pager->size()= "<<read_queue->size()<<" to delete = "<<read_queue->_childrenToDeleteList.size()<<std::endl; //
// delete any children if required.
//
if (_pager->_deleteRemovedSubgraphsInDatabaseThread/* && !(read_queue->_childrenToDeleteList.empty())*/)
{
ObjectList deleteList;
{
// Don't hold lock during destruction of deleteList
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(read_queue->_requestMutex);
if (!read_queue->_childrenToDeleteList.empty())
{
deleteList.swap(read_queue->_childrenToDeleteList);
read_queue->updateBlock();
}
}
} //
// load any subgraphs that are required.
//
osg::ref_ptr<DatabaseRequest> databaseRequest;
read_queue->takeFirst(databaseRequest); bool readFromFileCache = false; osg::ref_ptr<FileCache> fileCache = osgDB::Registry::instance()->getFileCache();
osg::ref_ptr<FileLocationCallback> fileLocationCallback = osgDB::Registry::instance()->getFileLocationCallback();
osg::ref_ptr<Options> dr_loadOptions;
std::string fileName;
int frameNumberLastRequest = ;
bool cacheNodes = false;
if (databaseRequest.valid())
{
{
OpenThreads::ScopedLock<OpenThreads::Mutex> drLock(_pager->_dr_mutex);
dr_loadOptions = databaseRequest->_loadOptions.valid() ? databaseRequest->_loadOptions->cloneOptions() : new osgDB::Options;
dr_loadOptions->setTerrain(databaseRequest->_terrain);
dr_loadOptions->setParentGroup(databaseRequest->_group);
fileName = databaseRequest->_fileName;
frameNumberLastRequest = databaseRequest->_frameNumberLastRequest;
} if (dr_loadOptions->getFileCache()) fileCache = dr_loadOptions->getFileCache();
if (dr_loadOptions->getFileLocationCallback()) fileLocationCallback = dr_loadOptions->getFileLocationCallback(); // disable the FileCache if the fileLocationCallback tells us that it isn't required for this request.
if (fileLocationCallback.valid() && !fileLocationCallback->useFileCache()) fileCache = ; cacheNodes = (dr_loadOptions->getObjectCacheHint() & osgDB::Options::CACHE_NODES)!=;
if (cacheNodes)
{
//OSG_NOTICE<<"Checking main ObjectCache"<<std::endl;
// check the object cache to see if the file we want has already been loaded.
osg::ref_ptr<osg::Object> objectFromCache = osgDB::Registry::instance()->getRefFromObjectCache(fileName); // if no object with fileName in ObjectCache then try the filename appropriate for fileCache
if (!objectFromCache && (fileCache.valid() && fileCache->isFileAppropriateForFileCache(fileName)))
{
if (fileCache->existsInCache(fileName))
{
objectFromCache = osgDB::Registry::instance()->getRefFromObjectCache(fileCache->createCacheFileName(fileName));
}
} osg::Node* modelFromCache = dynamic_cast<osg::Node*>(objectFromCache.get());
if (modelFromCache)
{
//OSG_NOTICE<<"Found object in cache "<<fileName<<std::endl; // assign the cached model to the request
{
OpenThreads::ScopedLock<OpenThreads::Mutex> drLock(_pager->_dr_mutex);
databaseRequest->_loadedModel = modelFromCache;
} // move the request to the dataToMerge list so it can be merged during the update phase of the frame.
{
OpenThreads::ScopedLock<OpenThreads::Mutex> listLock( _pager->_dataToMergeList->_requestMutex);
_pager->_dataToMergeList->addNoLock(databaseRequest.get());
databaseRequest = ;
} // skip the rest of the do/while loop as we have done all the processing we need to do.
continue;
}
else
{
//OSG_NOTICE<<"Not Found object in cache "<<fileName<<std::endl;
} // need to disable any attempt to use the cache when loading as we're handle this ourselves to avoid threading conflicts
{
OpenThreads::ScopedLock<OpenThreads::Mutex> drLock(_pager->_dr_mutex);
databaseRequest->_objectCache = new ObjectCache;
dr_loadOptions->setObjectCache(databaseRequest->_objectCache.get());
}
} // check if databaseRequest is still relevant
if ((_pager->_frameNumber-frameNumberLastRequest)<=)
{ // now check to see if this request is appropriate for this thread
switch(_mode)
{
case(HANDLE_ALL_REQUESTS):
{
// do nothing as this thread can handle the load
if (fileCache.valid() && fileCache->isFileAppropriateForFileCache(fileName))
{
if (fileCache->existsInCache(fileName))
{
readFromFileCache = true;
}
}
break;
}
case(HANDLE_NON_HTTP):
{
// check the cache first
bool isHighLatencyFileRequest = false; if (fileLocationCallback.valid())
{
isHighLatencyFileRequest = fileLocationCallback->fileLocation(fileName, dr_loadOptions.get()) == FileLocationCallback::REMOTE_FILE;
}
else if (fileCache.valid() && fileCache->isFileAppropriateForFileCache(fileName))
{
isHighLatencyFileRequest = true;
} if (isHighLatencyFileRequest)
{
if (fileCache.valid() && fileCache->existsInCache(fileName))
{
readFromFileCache = true;
}
else
{
OSG_INFO<<_name<<": Passing http requests over "<<fileName<<std::endl;
out_queue->add(databaseRequest.get());
databaseRequest = ;
}
}
break;
}
case(HANDLE_ONLY_HTTP):
{
// accept all requests, as we'll assume only high latency requests will have got here.
break;
}
}
}
else
{
databaseRequest = ;
}
} if (databaseRequest.valid())
{ // load the data, note safe to write to the databaseRequest since once
// it is created this thread is the only one to write to the _loadedModel pointer.
//OSG_NOTICE<<"In DatabasePager thread readNodeFile("<<databaseRequest->_fileName<<")"<<std::endl;
//osg::Timer_t before = osg::Timer::instance()->tick(); // assume that readNode is thread safe...
ReaderWriter::ReadResult rr = readFromFileCache ?
fileCache->readNode(fileName, dr_loadOptions.get(), false) :
Registry::instance()->readNode(fileName, dr_loadOptions.get(), false); osg::ref_ptr<osg::Node> loadedModel;
if (rr.validNode()) loadedModel = rr.getNode();
if (rr.error()) OSG_WARN<<"Error in reading file "<<fileName<<" : "<<rr.message() << std::endl;
if (rr.notEnoughMemory()) OSG_INFO<<"Not enought memory to load file "<<fileName << std::endl; if (loadedModel.valid() &&
fileCache.valid() &&
fileCache->isFileAppropriateForFileCache(fileName) &&
!readFromFileCache)
{
fileCache->writeNode(*(loadedModel), fileName, dr_loadOptions.get());
} {
OpenThreads::ScopedLock<OpenThreads::Mutex> drLock(_pager->_dr_mutex);
if ((_pager->_frameNumber-databaseRequest->_frameNumberLastRequest)>)
{
OSG_INFO<<_name<<": Warning DatabaseRquest no longer required."<<std::endl;
loadedModel = ;
}
} //OSG_NOTICE<<" node read in "<<osg::Timer::instance()->delta_m(before,osg::Timer::instance()->tick())<<" ms"<<std::endl; if (loadedModel.valid())
{
loadedModel->getBound(); bool loadedObjectsNeedToBeCompiled = false;
osg::ref_ptr<osgUtil::IncrementalCompileOperation::CompileSet> compileSet = ;
if (!rr.loadedFromCache())
{
// find all the compileable rendering objects
DatabasePager::FindCompileableGLObjectsVisitor stateToCompile(_pager, _pager->getMarkerObject());
loadedModel->accept(stateToCompile); loadedObjectsNeedToBeCompiled = _pager->_doPreCompile &&
_pager->_incrementalCompileOperation.valid() &&
_pager->_incrementalCompileOperation->requiresCompile(stateToCompile); // move the databaseRequest from the front of the fileRequest to the end of
// dataToCompile or dataToMerge lists.
if (loadedObjectsNeedToBeCompiled)
{
// OSG_NOTICE<<"Using IncrementalCompileOperation"<<std::endl; compileSet = new osgUtil::IncrementalCompileOperation::CompileSet(loadedModel.get());
compileSet->buildCompileMap(_pager->_incrementalCompileOperation->getContextSet(), stateToCompile);
compileSet->_compileCompletedCallback = new DatabasePagerCompileCompletedCallback(_pager, databaseRequest.get());
_pager->_incrementalCompileOperation->add(compileSet.get(), false);
}
}
else
{
OSG_NOTICE<<"Loaded from ObjectCache"<<std::endl;
} {
OpenThreads::ScopedLock<OpenThreads::Mutex> drLock(_pager->_dr_mutex);
databaseRequest->_loadedModel = loadedModel;
databaseRequest->_compileSet = compileSet;
}
// Dereference the databaseRequest while the queue is
// locked. This prevents the request from being
// deleted at an unpredictable time within
// addLoadedDataToSceneGraph.
if (loadedObjectsNeedToBeCompiled)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> listLock(
_pager->_dataToCompileList->_requestMutex);
_pager->_dataToCompileList->addNoLock(databaseRequest.get());
databaseRequest = ;
}
else
{
OpenThreads::ScopedLock<OpenThreads::Mutex> listLock(
_pager->_dataToMergeList->_requestMutex);
_pager->_dataToMergeList->addNoLock(databaseRequest.get());
databaseRequest = ;
} } // _pager->_dataToCompileList->pruneOldRequestsAndCheckIfEmpty();
}
else
{
OpenThreads::Thread::YieldCurrentThread();
} // go to sleep till our the next time our thread gets scheduled. if (firstTime)
{
// do a yield to get round a peculiar thread hang when testCancel() is called
// in certain circumstances - of which there is no particular pattern.
YieldCurrentThread();
firstTime = false;
} } while (!testCancel() && !_done);
}
[osg][osgearth]osg的分页加载,代码和结构图的更多相关文章
- java攻城狮之路(Android篇)--widget_webview_metadata_popupwindow_tabhost_分页加载数据_菜单
一.widget:桌面小控件1 写一个类extends AppWidgetProvider 2 在清单文件件中注册: <receiver android:name=".ExampleA ...
- Android基本控件之listView(三)<用ListView实现分页加载>
我们之前讨论了ListView的基本使用方法和ListView的优化 今天我们再来讨论一个关于ListView的一个新的东西~就是分页加载.那么什么是分页加载呢?简单点说,就是"下拉刷新&q ...
- ListView实现分页加载(三)实现分页加载
在上一篇中,我们实现了底部布局(即带上了进度条).没有读过的朋友可以点击下面的链接: http://www.cnblogs.com/fuly550871915/p/4866966.html 但是进度条 ...
- ListView实现分页加载(一)制作Demo
一.什么是分页加载 在下面的文章中,我们来讲解LitView分页加载的实现.什么是分页加载呢?我们先看几张效果图吧,如下: ...
- android中滑动SQLite数据库分页加载
今天用到了android中滑动SQlit数据库分页加载技术,写了个测试工程,将代码贴出来和大家交流一下: MainActivity package com.example.testscrollsqli ...
- iOS 高效的分页加载(TableView、CollectionView)
一.tableview的分页加载的代码对比 没有优化之前的代码如下 [strongSelf.tableView.mj_footer endRefreshing]: [strongSelf.articl ...
- 微信小程序云开发-列表数据分页加载显示
一.准备工作 1.创建数据库nums,向数据库中导入108条数据 2.修改数据库表nums的权限 二.新建页面ListPaginated 1.wxml文件 <!-- 显示列表数据 --> ...
- Android ListView分页加载时图片显示问题
场景:Android ListView需要分页加载,每个item中会有图片,图片又是从网络下载的. 问题:在滑动加载下一页时,上一页的图片明明已经下载完成了,但是无法显示出来. Bug重现: 1,加载 ...
- Android中ListView分页加载数据
public class MainActivity extends Activity { private ListView listView=null; //listview的数据填充器 privat ...
- Android动态加载代码技术
Android动态加载代码技术 在开发Android App的过程当中,可能希望实现插件式软件架构,将一部分代码以另外一个APK的形式单独发布,而在主程序中加载并执行这个APK中的代码. 实现这个任务 ...
随机推荐
- shell脚本关闭tomcat
使用shell脚本快速关闭tomcat,就是获取tomcat进程后,一起kill掉: #!/bin/sh #kill tomcat pid name=tomcat-emall pidlist=`ps ...
- JAVA学习基础知识总结(原创)
(未经博主允许,禁止转载!) 一.基础知识:1.JVM.JRE和JDK的区别: JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性. java语言是跨平 ...
- 【css预处理器】------sass的基本语法------【巷子】
001.安装sass 1.删除gem源:gem sources --remove https://rubygems.org/ 2.添加国内源:gem sources -a http://gems.ru ...
- Redis集群管理(二)
1.进入集群客户端 任意选一个redis节点,进入redis 所在目录 cd /redis 所在目录/src/ ./redis-cli -h 本地节点的ip -p redis的端口号 -a 密码 [r ...
- python使用MySqlDB
下载安装MySQLdb <1>linux版本 http://sourceforge.net/projects/mysql-python/ 下载,在安装是要先安装setuptools,然后在 ...
- 每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它
mybatis – MyBatis 3 | 入门 http://www.mybatis.org/mybatis-3/zh/getting-started.html 作用域(Scope)和生命周期 理解 ...
- SVN库迁移整理方法----官方推荐方式
以下是subversion官方推荐的备份方式. 关闭所有运行的进程,并确认没有程序在访问存储库(如 httpd.svnserve 或本地用户在直接访问). 备份svn存储库 #压缩备份 svnadmi ...
- python三层架构
conf/setting(配置文件) 一般是对utility进行相关设置 index(主文件) main函数触发某个对象的业务逻辑方法 model(数据库) admin 是对数据库的操 ...
- vue知识总汇
学前预备知识 ECMAScript简介和ES6的新增语法 Nodejs基础 webpack的介绍 babel简介 vue基础 vue基础
- (2.1)学习笔记之mysql基本操作(启动与关闭)
本系列学习笔记主要讲如下几个方面: 本文主要是[一:mysql启动][二:mysql关闭] 一..mysql启动 如图,有多重启动方式 (1.1)mysql.server start :默认使用 /e ...