diff --git a/include/osg/ImageSequence b/include/osg/ImageSequence index ecdd3339e..d6b40e955 100644 --- a/include/osg/ImageSequence +++ b/include/osg/ImageSequence @@ -105,6 +105,7 @@ class OSG_EXPORT ImageSequence : public ImageStream Images _images; Images::iterator _imageIterator; double _imageIteratorTime; + }; } // namespace diff --git a/include/osg/NodeVisitor b/include/osg/NodeVisitor index 4b3bd75ce..53c4cd1d9 100644 --- a/include/osg/NodeVisitor +++ b/include/osg/NodeVisitor @@ -292,7 +292,7 @@ class OSG_EXPORT NodeVisitor : public virtual Referenced ImageRequestHandler(): Referenced(true) {} - virtual void requestNodeFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const FrameStamp* framestamp, osg::ref_ptr& imageRequest) = 0; + virtual void requestImageFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const FrameStamp* framestamp) = 0; protected: virtual ~ImageRequestHandler() {} diff --git a/include/osgDB/ImagePager b/include/osgDB/ImagePager index 4162342ee..05552c1a0 100644 --- a/include/osgDB/ImagePager +++ b/include/osgDB/ImagePager @@ -16,8 +16,9 @@ #include #include +#include +#include -#include #include #include @@ -30,7 +31,11 @@ class OSGDB_EXPORT ImagePager : public osg::NodeVisitor::ImageRequestHandler public: ImagePager(); - + + + // forward declare + struct RequestQueue; + struct ImageRequest : public osg::Referenced { ImageRequest(): @@ -40,11 +45,49 @@ class OSGDB_EXPORT ImagePager : public osg::NodeVisitor::ImageRequestHandler double _timeToMergeBy; std::string _fileName; osg::ref_ptr _loadOptions; - osg::ref_ptr _objectToAttachTo; + osg::observer_ptr _objectToAttachTo; osg::ref_ptr _loadedImage; - + RequestQueue* _requestQueue; + }; + struct RequestQueue : public osg::Referenced + { + typedef std::vector< osg::ref_ptr > RequestList; + + void sort(); + + RequestList _requestList; + OpenThreads::Mutex _requestMutex; + }; + + + struct ReadQueue : public RequestQueue + { + ReadQueue(ImagePager* pager, const std::string& name); + + void block() { _block->block(); } + + void release() { _block->release(); } + + void updateBlock() + { + _block->set((!_requestList.empty() || !_pager->_databasePagerThreadPaused)); + } + + void clear(); + + void add(ImageRequest* imageRequest); + + void takeFirst(osg::ref_ptr& databaseRequest); + + osg::ref_ptr _block; + + ImagePager* _pager; + std::string _name; + }; + + class OSGDB_EXPORT ImageThread : public osg::Referenced, public OpenThreads::Thread { public: @@ -72,22 +115,34 @@ class OSGDB_EXPORT ImagePager : public osg::NodeVisitor::ImageRequestHandler virtual ~ImageThread(); bool _done; - ImagePager* _pager; Mode _mode; + ImagePager* _pager; std::string _name; }; - virtual void requestNodeFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const osg::FrameStamp* framestamp, osg::ref_ptr& imageRequest); + virtual void requestImageFile(const std::string& fileName,osg::Object* attachmentPoint, double timeToMergeBy, const osg::FrameStamp* framestamp); /** Return true if there are pending updates to the scene graph that require a call to updateSceneGraph(double). */ virtual bool requiresUpdateSceneGraph() const; /** Merge the changes to the scene graph. */ virtual void updateSceneGraph(double currentFrameTime); + + int cancel(); public: virtual ~ImagePager(); + + OpenThreads::Mutex _run_mutex; + bool _startThreadCalled; + + bool _done; + bool _databasePagerThreadPaused; + + osg::ref_ptr _readQueue; + osg::ref_ptr _imageThread; + }; diff --git a/src/osg/ImageSequence.cpp b/src/osg/ImageSequence.cpp index ee33ecd32..e1b1158bf 100644 --- a/src/osg/ImageSequence.cpp +++ b/src/osg/ImageSequence.cpp @@ -44,7 +44,7 @@ ImageSequence::ImageSequence() _duration = 1.0; _preLoadTime = 1.0; _timePerImage = 1.0; - _pruneOldImages = false; + _pruneOldImages = true; _fileNamesIterator = _fileNames.end(); _fileNamesIteratorTime = DBL_MAX; @@ -153,10 +153,12 @@ void ImageSequence::update(osg::NodeVisitor* nv) double time = (fs->getSimulationTime() - _referenceTime)*_timeMultiplier; double preLoadTime = (time+_preLoadTime)*_timeMultiplier; + FileNames::iterator previous_fileNamesIterator = _fileNamesIterator; Images::iterator previous_imageIterator = _imageIterator; // osg::notify(osg::NOTICE)<<"time = "< read_queue; + + switch(_mode) + { + case(HANDLE_ALL_REQUESTS): + read_queue = _pager->_readQueue; + break; + case(HANDLE_NON_HTTP): + read_queue = _pager->_readQueue; + break; + case(HANDLE_ONLY_HTTP): + read_queue = _pager->_readQueue; + break; + } + + do + { + read_queue->block(); + + osg::ref_ptr imageRequest; + read_queue->takeFirst(imageRequest); + + if (imageRequest.valid()) + { + osg::ref_ptr image = osgDB::readImageFile(imageRequest->_fileName); + if (image.valid()) + { + osg::ImageSequence* is = dynamic_cast(imageRequest->_objectToAttachTo.get()); + if (is) + { + is->addImage(image.get()); + } + else + { + osg::Texture* texture = dynamic_cast(imageRequest->_objectToAttachTo.get()); + if (texture) + { + texture->setImage(0, image.get()); + } + } + } + + } + + 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::notify(osg::NOTICE)<<"ImagePager::ImageThread::done()"<& imageRequest) +int ImagePager::cancel() { - osg::notify(osg::NOTICE)<<"ImagePager::requestNodeFile("<setDone(true); + + // release the frameBlock and _databasePagerThreadBlock in case its holding up thread cancellation. + _readQueue->release(); + + _imageThread->cancel(); + + _done = true; + _startThreadCalled = false; + + //std::cout<<"DatabasePager::~DatabasePager() stopped running"< request = new ImageRequest; + request->_timeToMergeBy = timeToMergeBy; + request->_fileName = fileName; + request->_objectToAttachTo = attachmentPoint; + request->_requestQueue = _readQueue.get(); + + _readQueue->add(request.get()); + + if (!_startThreadCalled) + { + OpenThreads::ScopedLock lock(_run_mutex); + + if (!_startThreadCalled) + { + _startThreadCalled = true; + _done = false; + _imageThread->startThread(); + + } + } } bool ImagePager::requiresUpdateSceneGraph() const