1 // Copyright (C) 2008 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
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 GNU
11 // Library General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 #include "BVHPager.hxx"
22 #include <simgear/threads/SGThread.hxx>
23 #include <simgear/threads/SGGuard.hxx>
25 #include "BVHPageNode.hxx"
26 #include "BVHPageRequest.hxx"
30 struct BVHPager::_PrivateData : protected SGThread {
31 typedef SGSharedPtr<BVHPageRequest> _Request;
32 typedef std::list<_Request> _RequestList;
33 typedef std::list<SGSharedPtr<BVHPageNode> > _PageNodeList;
36 void _push(const _Request& request)
38 SGGuard<SGMutex> scopeLock(_mutex);
39 _requestList.push_back(request);
43 SGGuard<SGMutex> scopeLock(_mutex);
44 if (_requestList.empty())
47 request.swap(_requestList.front());
48 _requestList.pop_front();
53 _RequestList _requestList;
61 void _push(const _Request& request)
63 SGGuard<SGMutex> scopeLock(_mutex);
64 bool needSignal = _requestList.empty();
65 _requestList.push_back(request);
67 _waitCondition.signal();
71 SGGuard<SGMutex> scopeLock(_mutex);
72 while (_requestList.empty())
73 _waitCondition.wait(_mutex);
75 request.swap(_requestList.front());
76 _requestList.pop_front();
81 SGWaitCondition _waitCondition;
82 _RequestList _requestList;
90 virtual ~_PrivateData()
98 _Request request = _pendingRequests._pop();
99 // This means stop working
100 if (!request.valid())
103 _processedRequests._push(request);
121 // send a stop request ...
122 _pendingRequests._stop();
123 // ... and wait for the thread to finish
128 void _use(BVHPageNode& pageNode)
130 if (pageNode._requested) {
131 // move it forward in the lru list
132 _pageNodeList.splice(_pageNodeList.end(), _pageNodeList,
135 _Request request = pageNode.newRequest();
136 if (!request.valid())
139 pageNode._iterator = _pageNodeList.insert(_pageNodeList.end(),
141 pageNode._requested = true;
144 _pendingRequests._push(request);
150 pageNode._useStamp = _useStamp;
153 void _update(unsigned expiry)
155 // Insert all processed requests
157 SGSharedPtr<BVHPageRequest> request;
158 request = _processedRequests._pop();
159 if (!request.valid())
164 // ... and throw away stuff that is not used for a long time
165 unsigned useStamp = _useStamp - expiry;
166 _PageNodeList::iterator i = _pageNodeList.begin();
167 while (i != _pageNodeList.end()) {
168 // Ok, this means if the highest bit in the below difference
169 // is set which is aequivalent to having a negative difference
170 // but being wraparound save.
171 unsigned diff = (*i)->_useStamp - useStamp;
172 // test the sign bit of the difference
173 if (!(diff & (~((~0u) >> 1))))
176 (*i)->_requested = false;
177 i = _pageNodeList.erase(i);
183 _WorkQueue _pendingRequests;
184 _LockedQueue _processedRequests;
185 // Store the rcu list of loaded nodes so that they can expire
186 _PageNodeList _pageNodeList;
189 BVHPager::BVHPager() :
190 _privateData(new _PrivateData)
194 BVHPager::~BVHPager()
203 return _privateData->_start();
209 _privateData->_stop();
213 BVHPager::use(BVHPageNode& pageNode)
215 _privateData->_use(pageNode);
219 BVHPager::update(unsigned expiry)
221 _privateData->_update(expiry);
225 BVHPager::setUseStamp(unsigned stamp)
227 _privateData->_useStamp = stamp;
231 BVHPager::getUseStamp() const
233 return _privateData->_useStamp;