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的分页加载,代码和结构图的更多相关文章

  1. java攻城狮之路(Android篇)--widget_webview_metadata_popupwindow_tabhost_分页加载数据_菜单

    一.widget:桌面小控件1 写一个类extends AppWidgetProvider 2 在清单文件件中注册: <receiver android:name=".ExampleA ...

  2. Android基本控件之listView(三)<用ListView实现分页加载>

    我们之前讨论了ListView的基本使用方法和ListView的优化 今天我们再来讨论一个关于ListView的一个新的东西~就是分页加载.那么什么是分页加载呢?简单点说,就是"下拉刷新&q ...

  3. ListView实现分页加载(三)实现分页加载

    在上一篇中,我们实现了底部布局(即带上了进度条).没有读过的朋友可以点击下面的链接: http://www.cnblogs.com/fuly550871915/p/4866966.html 但是进度条 ...

  4. ListView实现分页加载(一)制作Demo

    一.什么是分页加载 在下面的文章中,我们来讲解LitView分页加载的实现.什么是分页加载呢?我们先看几张效果图吧,如下:                                       ...

  5. android中滑动SQLite数据库分页加载

    今天用到了android中滑动SQlit数据库分页加载技术,写了个测试工程,将代码贴出来和大家交流一下: MainActivity package com.example.testscrollsqli ...

  6. iOS 高效的分页加载(TableView、CollectionView)

    一.tableview的分页加载的代码对比 没有优化之前的代码如下 [strongSelf.tableView.mj_footer endRefreshing]: [strongSelf.articl ...

  7. 微信小程序云开发-列表数据分页加载显示

    一.准备工作 1.创建数据库nums,向数据库中导入108条数据 2.修改数据库表nums的权限 二.新建页面ListPaginated 1.wxml文件 <!-- 显示列表数据 --> ...

  8. Android ListView分页加载时图片显示问题

    场景:Android ListView需要分页加载,每个item中会有图片,图片又是从网络下载的. 问题:在滑动加载下一页时,上一页的图片明明已经下载完成了,但是无法显示出来. Bug重现: 1,加载 ...

  9. Android中ListView分页加载数据

    public class MainActivity extends Activity { private ListView listView=null; //listview的数据填充器 privat ...

  10. Android动态加载代码技术

    Android动态加载代码技术 在开发Android App的过程当中,可能希望实现插件式软件架构,将一部分代码以另外一个APK的形式单独发布,而在主程序中加载并执行这个APK中的代码. 实现这个任务 ...

随机推荐

  1. angular -- 无刷新做分页

    无刷新做分页参考地址: http://www.jq22.com/demo/angular201707111100/ 示例代码: <!DOCTYPE html> <html lang= ...

  2. javaWeb项目springMVC框架下利用ITextpdf 工具打印PDF文件的方法(打印表单、插入图片)

    方法一:打印PDF表单以及在PDF中加入图片 需要的资料: jar包:iTextAsian.jar ,itext-2.1.7.jar: 源码: public static void main(Stri ...

  3. maven学习(一)(转)

    我记得在搞懂maven之前看了几次重复的maven的教学视频.不知道是自己悟性太低还是怎么滴,就是搞不清楚,现在弄清楚了,基本上入门了.写该篇博文,就是为了帮助那些和我一样对于maven迷迷糊糊的人. ...

  4. SaltStack部署redis主从

    需求: 一,部署redis主从,一台主一台从 二,redis监听自己的IP地址,而不是0.0.0.0 主:安装,配置,启动 从:安装,配置,启动,主从

  5. [ASP.NET]从Request.Url获取根网址的最简单方法

    在拼接绝对路径的网址时,经常需要从Request.Url中获取根网址(比如http://www.cnblogs.com),然后与相对路径一起拼接为绝对路径. 以前的做法如下: var uri = Re ...

  6. SQL的子查询操作

    对于表中的每一个记录,我们有时候需要提取特殊的或者你需要的记录,要提前做一个表的筛选,之后再对你选出的记录做一个修改,此时你必须使用SQL的子查询操作.如:修改id=5的记录的strContent字段 ...

  7. SVN跨版本库迁移目录并保留提交日志

    现在有一份代码code在版本库reposA/dirB/下,现在想把它移动到reposB/dirAA/下,本来打算交给SA做,没想到SA似乎 也不太懂的样子.于是,自己在VPS搭建了一个svnserve ...

  8. flask源码剖析--请求流程

    想了解这篇里面的内容,请先去了解我另外一篇博客Flask上下文 在了解flask之前,我们需要了解两个小知识点 偏函数 import functools def func(a1,a2): print( ...

  9. python调用C++之pybind11入门(相互调用)

    python调用C/C++有不少的方法,如boost.python, swig, ctypes, pybind11等,这些方法有繁有简,而pybind11的优点是对C++ 11支持很好,API比较简单 ...

  10. django后台获取相同name名的数据

    django后台获取相同name名的post数据html: <form method="post"> <input type="text" n ...