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