root/OpenSceneGraph/trunk/src/osgDB/ImagePager.cpp @ 13041

Revision 13041, 9.9 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgDB/ImagePager>
15#include <osgDB/ReadFile>
16
17#include <osg/Notify>
18#include <osg/ImageSequence>
19
20using namespace osgDB;
21
22
23/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
24//
25//  SortFileRequestFunctor
26//
27struct ImagePager::SortFileRequestFunctor
28{
29    bool operator() (const osg::ref_ptr<ImagePager::ImageRequest>& lhs,const osg::ref_ptr<ImagePager::ImageRequest>& rhs) const
30    {
31        return (lhs->_timeToMergeBy < rhs->_timeToMergeBy);
32    }
33};
34
35
36/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
37//
38//  ReadQueue
39//
40void ImagePager::RequestQueue::sort()
41{
42    std::sort(_requestList.begin(),_requestList.end(),SortFileRequestFunctor());
43}
44
45
46/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
47//
48//  ReadQueue
49//
50ImagePager::ReadQueue::ReadQueue(ImagePager* pager, const std::string& name):
51    _pager(pager),
52    _name(name)
53{
54    _block = new osg::RefBlock;
55}
56
57void ImagePager::ReadQueue::clear()
58{
59    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_requestMutex);
60
61    for(RequestList::iterator citr = _requestList.begin();
62        citr != _requestList.end();
63        ++citr)
64    {
65        (*citr)->_attachmentPoint = 0;
66        (*citr)->_requestQueue = 0;
67    }
68
69    _requestList.clear();
70
71    updateBlock();
72}
73
74void ImagePager::ReadQueue::add(ImagePager::ImageRequest* databaseRequest)
75{
76    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_requestMutex);
77    _requestList.push_back(databaseRequest);
78    databaseRequest->_requestQueue = this;
79
80    updateBlock();
81}
82
83void ImagePager::ReadQueue::takeFirst(osg::ref_ptr<ImageRequest>& databaseRequest)
84{
85    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_requestMutex);
86
87    if (!_requestList.empty())
88    {
89        sort();
90
91        databaseRequest = _requestList.front();
92        databaseRequest->_requestQueue = 0;
93        _requestList.erase(_requestList.begin());
94
95        updateBlock();
96    }
97}
98
99//////////////////////////////////////////////////////////////////////////////////////
100//
101// ImageThread
102//
103ImagePager::ImageThread::ImageThread(ImagePager* pager, Mode mode, const std::string& name):
104    _done(false),
105    _mode(mode),
106    _pager(pager),
107    _name(name)
108{
109}
110
111ImagePager::ImageThread::ImageThread(const ImageThread& dt, ImagePager* pager):
112    _done(false),
113    _mode(dt._mode),
114    _pager(pager),
115    _name(dt._name)
116{
117}
118
119ImagePager::ImageThread::~ImageThread()
120{
121}
122
123int ImagePager::ImageThread::cancel()
124{
125    int result = 0;
126
127    if( isRunning() )
128    {
129
130        _done = true;
131
132        switch(_mode)
133        {
134            case(HANDLE_ALL_REQUESTS):
135                _pager->_readQueue->release();
136                break;
137            case(HANDLE_NON_HTTP):
138                _pager->_readQueue->release();
139                break;
140            case(HANDLE_ONLY_HTTP):
141                _pager->_readQueue->release();
142                break;
143        }
144
145        // release the frameBlock and _databasePagerThreadBlock in case its holding up thread cancellation.
146        // _databasePagerThreadBlock->release();
147
148        // then wait for the the thread to stop running.
149        while(isRunning())
150        {
151            // commenting out debug info as it was cashing crash on exit, presumable
152            // due to osg::notify or std::cout destructing earlier than this destructor.
153            // OSG_DEBUG<<"Waiting for DatabasePager to cancel"<<std::endl;
154            OpenThreads::Thread::YieldCurrentThread();
155        }
156
157        // _startThreadCalled = false;
158    }
159    //std::cout<<"DatabasePager::~DatabasePager() stopped running"<<std::endl;
160    return result;
161}
162
163void ImagePager::ImageThread::run()
164{
165    OSG_INFO<<"ImagePager::ImageThread::run() "<<this<<std::endl;
166    bool firstTime = true;
167
168    osg::ref_ptr<ImagePager::ReadQueue> read_queue;
169
170    switch(_mode)
171    {
172        case(HANDLE_ALL_REQUESTS):
173            read_queue = _pager->_readQueue;
174            break;
175        case(HANDLE_NON_HTTP):
176            read_queue = _pager->_readQueue;
177            break;
178        case(HANDLE_ONLY_HTTP):
179            read_queue = _pager->_readQueue;
180            break;
181    }
182
183    do
184    {
185        read_queue->block();
186
187        osg::ref_ptr<ImageRequest> imageRequest;
188        read_queue->takeFirst(imageRequest);
189
190        if (imageRequest.valid())
191        {
192            osg::ref_ptr<osg::Image> image = osgDB::readImageFile(imageRequest->_fileName);
193            if (image.valid())
194            {
195                osg::ImageSequence* is = dynamic_cast<osg::ImageSequence*>(imageRequest->_attachmentPoint.get());
196                if (is)
197                {
198                    if (imageRequest->_attachmentIndex >= 0)
199                    {
200                        is->setImage(imageRequest->_attachmentIndex, image.get());
201                    }
202                    else
203                    {
204                        is->addImage(image.get());
205                    }
206                }
207                else
208                {
209                    imageRequest->_loadedImage = image;
210
211                    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_pager->_completedQueue->_requestMutex);
212                    _pager->_completedQueue->_requestList.push_back(imageRequest);
213                }
214            }
215
216        }
217        else
218        {
219            OpenThreads::Thread::YieldCurrentThread();
220        }
221
222
223        // go to sleep till our the next time our thread gets scheduled.
224
225        if (firstTime)
226        {
227            // do a yield to get round a peculiar thread hang when testCancel() is called
228            // in certain circumstances - of which there is no particular pattern.
229            YieldCurrentThread();
230            firstTime = false;
231        }
232
233    } while (!testCancel() && !_done);
234
235    OSG_INFO<<"ImagePager::ImageThread::done()"<<std::endl;
236
237}
238
239//////////////////////////////////////////////////////////////////////////////////////
240//
241// ImagePager
242//
243ImagePager::ImagePager():
244    _done(false)
245{
246    _startThreadCalled = false;
247    _databasePagerThreadPaused = false;
248
249    _readQueue = new ReadQueue(this,"Image Queue");
250    _completedQueue = new RequestQueue;
251    _imageThreads.push_back(new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread 1"));
252    //_imageThreads.push_back(new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread 2"));
253    //_imageThreads.push_back(new ImageThread(this, ImageThread::HANDLE_ALL_REQUESTS, "Image Thread 3"));
254
255    // 1 second
256    _preLoadTime = 1.0;
257}
258
259ImagePager::~ImagePager()
260{
261    cancel();
262}
263
264int ImagePager::cancel()
265{
266    int result = 0;
267
268    for(ImageThreads::iterator itr = _imageThreads.begin();
269        itr != _imageThreads.end();
270        ++itr)
271    {
272        (*itr)->setDone(true);
273    }
274
275    // release the frameBlock and _databasePagerThreadBlock in case its holding up thread cancellation.
276    _readQueue->release();
277
278    for(ImageThreads::iterator itr = _imageThreads.begin();
279        itr != _imageThreads.end();
280        ++itr)
281    {
282        (*itr)->cancel();
283    }
284
285    _done = true;
286    _startThreadCalled = false;
287
288    //std::cout<<"DatabasePager::~DatabasePager() stopped running"<<std::endl;
289    return result;
290}
291
292osg::Image* ImagePager::readImageFile(const std::string& fileName)
293{
294    return osgDB::readImageFile(fileName);
295}
296
297void ImagePager::requestImageFile(const std::string& fileName,osg::Object* attachmentPoint, int attachmentIndex, double timeToMergeBy, const osg::FrameStamp*)
298{
299    OSG_INFO<<"ImagePager::requestNodeFile("<<fileName<<")"<<std::endl;
300
301    osg::ref_ptr<ImageRequest> request = new ImageRequest;
302    request->_timeToMergeBy = timeToMergeBy;
303    request->_fileName = fileName;
304    request->_attachmentPoint = attachmentPoint;
305    request->_attachmentIndex = attachmentIndex;
306    request->_requestQueue = _readQueue.get();
307
308    _readQueue->add(request.get());
309
310    if (!_startThreadCalled)
311    {
312        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_run_mutex);
313
314        if (!_startThreadCalled)
315        {
316            _startThreadCalled = true;
317            _done = false;
318
319            for(ImageThreads::iterator itr = _imageThreads.begin();
320                itr != _imageThreads.end();
321                ++itr)
322            {
323                (*itr)->startThread();
324            }
325
326        }
327    }
328}
329
330bool ImagePager::requiresUpdateSceneGraph() const
331{
332    //OSG_NOTICE<<"ImagePager::requiresUpdateSceneGraph()"<<std::endl;
333    return !(_completedQueue->_requestList.empty());
334}
335
336void ImagePager::updateSceneGraph(const osg::FrameStamp&)
337{
338    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_completedQueue->_requestMutex);
339
340    for(RequestQueue::RequestList::iterator itr = _completedQueue->_requestList.begin();
341        itr != _completedQueue->_requestList.end();
342        ++itr)
343    {
344        ImageRequest* imageRequest = itr->get();
345        osg::Texture* texture = dynamic_cast<osg::Texture*>(imageRequest->_attachmentPoint.get());
346        if (texture)
347        {
348            int attachmentIndex = imageRequest->_attachmentIndex > 0 ? imageRequest->_attachmentIndex : 0;
349            texture->setImage(attachmentIndex, imageRequest->_loadedImage.get());
350        }
351        else
352        {
353            OSG_NOTICE<<"ImagePager::updateSceneGraph() : error, image request attachment type not handled yet."<<std::endl;
354        }
355    }
356
357    _completedQueue->_requestList.clear();
358}
Note: See TracBrowser for help on using the browser.