xref: /AOO41X/main/sd/source/ui/slidesorter/cache/SlsRequestQueue.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "precompiled_sd.hxx"
29 
30 #include "SlsRequestQueue.hxx"
31 
32 #include <set>
33 
34 
35 #undef VERBOSE
36 //#define VERBOSE
37 
38 namespace sd { namespace slidesorter { namespace cache {
39 
40 /** This class extends the actual request data with additional information
41     that is used by the priority queues.
42 */
43 class Request
44 {
45 public:
46     Request (
47         CacheKey aKey, sal_Int32 nPriority, RequestPriorityClass eClass)
48         : maKey(aKey), mnPriorityInClass(nPriority), meClass(eClass)
49     {}
50     /** Sort requests according to priority classes and then to priorities.
51     */
52     class Comparator { public:
53         bool operator() (const Request& rRequest1, const Request& rRequest2)
54         {
55             if (rRequest1.meClass == rRequest2.meClass)
56                 return (rRequest1.mnPriorityInClass > rRequest2.mnPriorityInClass);
57             else
58                 return (rRequest1.meClass < rRequest2.meClass);
59         }
60     };
61     /** Request data is compared arbitrarily by their addresses in memory.
62         This just establishes an order so that the STL containers are happy.
63         The order is not semantically interpreted.
64     */
65     class DataComparator { public:
66         DataComparator (const Request&rRequest):maKey(rRequest.maKey){}
67         DataComparator (const CacheKey aKey):maKey(aKey){}
68         bool operator() (const Request& rRequest) { return maKey == rRequest.maKey; }
69     private: const CacheKey maKey;
70     };
71 
72     CacheKey maKey;
73     sal_Int32 mnPriorityInClass;
74     RequestPriorityClass meClass;
75 };
76 
77 
78 class RequestQueue::Container
79     : public ::std::set<
80         Request,
81         Request::Comparator>
82 {
83 };
84 
85 
86 
87 
88 //=====  GenericRequestQueue  =================================================
89 
90 
91 RequestQueue::RequestQueue (const SharedCacheContext& rpCacheContext)
92     : maMutex(),
93       mpRequestQueue(new Container()),
94       mpCacheContext(rpCacheContext),
95       mnMinimumPriority(0),
96       mnMaximumPriority(1)
97 {
98 }
99 
100 
101 
102 
103 RequestQueue::~RequestQueue (void)
104 {
105 }
106 
107 
108 
109 
110 void RequestQueue::AddRequest (
111     CacheKey aKey,
112     RequestPriorityClass eRequestClass,
113     bool /*bInsertWithHighestPriority*/)
114 {
115     ::osl::MutexGuard aGuard (maMutex);
116 
117     OSL_ASSERT(eRequestClass>=MIN__CLASS && eRequestClass<=MAX__CLASS);
118 
119     // If the request is already a member of the queue then remove it so
120     // that the following insertion will use the new prioritization.
121 #ifdef VERBOSE
122     bool bRemoved =
123 #endif
124 		RemoveRequest(aKey);
125 
126     // The priority of the request inside its priority class is defined by
127     // the page number.  This ensures a strict top-to-bottom, left-to-right
128     // order.
129     sal_Int32 nPriority (mpCacheContext->GetPriority(aKey));
130     Request aRequest (aKey, nPriority, eRequestClass);
131     mpRequestQueue->insert(aRequest);
132 
133     SSCD_SET_REQUEST_CLASS(rRequestData.GetPage(),eRequestClass);
134 
135 #ifdef VERBOSE
136     OSL_TRACE("%s request for page %d with priority class %d",
137         bRemoved?"replaced":"added",
138         (rRequestData.GetPage()->GetPageNum()-1)/2,
139         eRequestClass);
140 #endif
141 }
142 
143 
144 
145 
146 bool RequestQueue::RemoveRequest (
147     CacheKey aKey)
148 {
149     bool bRequestWasRemoved (false);
150     ::osl::MutexGuard aGuard (maMutex);
151 
152     while(true)
153     {
154         Container::const_iterator aRequestIterator = ::std::find_if (
155             mpRequestQueue->begin(),
156             mpRequestQueue->end(),
157             Request::DataComparator(aKey));
158         if (aRequestIterator != mpRequestQueue->end())
159         {
160             if (aRequestIterator->mnPriorityInClass == mnMinimumPriority+1)
161                 mnMinimumPriority++;
162             else if (aRequestIterator->mnPriorityInClass == mnMaximumPriority-1)
163                 mnMaximumPriority--;
164             mpRequestQueue->erase(aRequestIterator);
165             bRequestWasRemoved = true;
166 
167             if (bRequestWasRemoved)
168             {
169                 SSCD_SET_STATUS(rRequest.GetPage(),NONE);
170             }
171         }
172         else
173             break;
174     }
175 
176     return bRequestWasRemoved;
177 }
178 
179 
180 
181 
182 void RequestQueue::ChangeClass (
183     CacheKey aKey,
184     RequestPriorityClass eNewRequestClass)
185 {
186     ::osl::MutexGuard aGuard (maMutex);
187 
188     OSL_ASSERT(eNewRequestClass>=MIN__CLASS && eNewRequestClass<=MAX__CLASS);
189 
190     Container::const_iterator iRequest (
191         ::std::find_if (
192             mpRequestQueue->begin(),
193             mpRequestQueue->end(),
194             Request::DataComparator(aKey)));
195     if (iRequest!=mpRequestQueue->end() && iRequest->meClass!=eNewRequestClass)
196     {
197         AddRequest(aKey, eNewRequestClass, true);
198         SSCD_SET_REQUEST_CLASS(rRequestData.GetPage(),eNewRequestClass);
199     }
200 }
201 
202 
203 
204 
205 CacheKey RequestQueue::GetFront (void)
206 {
207     ::osl::MutexGuard aGuard (maMutex);
208 
209     if (mpRequestQueue->empty())
210         throw ::com::sun::star::uno::RuntimeException(
211             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
212                 "RequestQueue::GetFront(): queue is empty")),
213             NULL);
214 
215     return mpRequestQueue->begin()->maKey;
216 }
217 
218 
219 
220 
221 RequestPriorityClass RequestQueue::GetFrontPriorityClass (void)
222 {
223     ::osl::MutexGuard aGuard (maMutex);
224 
225     if (mpRequestQueue->empty())
226         throw ::com::sun::star::uno::RuntimeException(
227             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
228                 "RequestQueue::GetFrontPriorityClass(): queue is empty")),
229             NULL);
230 
231     return mpRequestQueue->begin()->meClass;
232 }
233 
234 
235 
236 
237 void RequestQueue::PopFront (void)
238 {
239     ::osl::MutexGuard aGuard (maMutex);
240 
241     if ( ! mpRequestQueue->empty())
242     {
243         SSCD_SET_STATUS(maRequestQueue.begin()->mpData->GetPage(),NONE);
244 
245         mpRequestQueue->erase(mpRequestQueue->begin());
246 
247         // Reset the priority counter if possible.
248         if (mpRequestQueue->empty())
249         {
250             mnMinimumPriority = 0;
251             mnMaximumPriority = 1;
252         }
253     }
254 }
255 
256 
257 
258 
259 bool RequestQueue::IsEmpty (void)
260 {
261     ::osl::MutexGuard aGuard (maMutex);
262     return mpRequestQueue->empty();
263 }
264 
265 
266 
267 
268 void RequestQueue::Clear (void)
269 {
270     ::osl::MutexGuard aGuard (maMutex);
271 
272     mpRequestQueue->clear();
273     mnMinimumPriority = 0;
274     mnMaximumPriority = 1;
275 }
276 
277 
278 
279 
280 ::osl::Mutex& RequestQueue::GetMutex (void)
281 {
282     return maMutex;
283 }
284 
285 
286 } } } // end of namespace ::sd::slidesorter::cache
287 
288 
289 
290