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