/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "precompiled_sd.hxx" #include "SlsRequestQueue.hxx" #include #undef VERBOSE //#define VERBOSE namespace sd { namespace slidesorter { namespace cache { /** This class extends the actual request data with additional information that is used by the priority queues. */ class Request { public: Request ( CacheKey aKey, sal_Int32 nPriority, RequestPriorityClass eClass) : maKey(aKey), mnPriorityInClass(nPriority), meClass(eClass) {} /** Sort requests according to priority classes and then to priorities. */ class Comparator { public: bool operator() (const Request& rRequest1, const Request& rRequest2) { if (rRequest1.meClass == rRequest2.meClass) return (rRequest1.mnPriorityInClass > rRequest2.mnPriorityInClass); else return (rRequest1.meClass < rRequest2.meClass); } }; /** Request data is compared arbitrarily by their addresses in memory. This just establishes an order so that the STL containers are happy. The order is not semantically interpreted. */ class DataComparator { public: DataComparator (const Request&rRequest):maKey(rRequest.maKey){} DataComparator (const CacheKey aKey):maKey(aKey){} bool operator() (const Request& rRequest) { return maKey == rRequest.maKey; } private: const CacheKey maKey; }; CacheKey maKey; sal_Int32 mnPriorityInClass; RequestPriorityClass meClass; }; class RequestQueue::Container : public ::std::set< Request, Request::Comparator> { }; //===== GenericRequestQueue ================================================= RequestQueue::RequestQueue (const SharedCacheContext& rpCacheContext) : maMutex(), mpRequestQueue(new Container()), mpCacheContext(rpCacheContext), mnMinimumPriority(0), mnMaximumPriority(1) { } RequestQueue::~RequestQueue (void) { } void RequestQueue::AddRequest ( CacheKey aKey, RequestPriorityClass eRequestClass, bool /*bInsertWithHighestPriority*/) { ::osl::MutexGuard aGuard (maMutex); OSL_ASSERT(eRequestClass>=MIN__CLASS && eRequestClass<=MAX__CLASS); // If the request is already a member of the queue then remove it so // that the following insertion will use the new prioritization. #ifdef VERBOSE bool bRemoved = #endif RemoveRequest(aKey); // The priority of the request inside its priority class is defined by // the page number. This ensures a strict top-to-bottom, left-to-right // order. sal_Int32 nPriority (mpCacheContext->GetPriority(aKey)); Request aRequest (aKey, nPriority, eRequestClass); mpRequestQueue->insert(aRequest); SSCD_SET_REQUEST_CLASS(rRequestData.GetPage(),eRequestClass); #ifdef VERBOSE OSL_TRACE("%s request for page %d with priority class %d", bRemoved?"replaced":"added", (rRequestData.GetPage()->GetPageNum()-1)/2, eRequestClass); #endif } bool RequestQueue::RemoveRequest ( CacheKey aKey) { bool bRequestWasRemoved (false); ::osl::MutexGuard aGuard (maMutex); while(true) { Container::const_iterator aRequestIterator = ::std::find_if ( mpRequestQueue->begin(), mpRequestQueue->end(), Request::DataComparator(aKey)); if (aRequestIterator != mpRequestQueue->end()) { if (aRequestIterator->mnPriorityInClass == mnMinimumPriority+1) mnMinimumPriority++; else if (aRequestIterator->mnPriorityInClass == mnMaximumPriority-1) mnMaximumPriority--; mpRequestQueue->erase(aRequestIterator); bRequestWasRemoved = true; if (bRequestWasRemoved) { SSCD_SET_STATUS(rRequest.GetPage(),NONE); } } else break; } return bRequestWasRemoved; } void RequestQueue::ChangeClass ( CacheKey aKey, RequestPriorityClass eNewRequestClass) { ::osl::MutexGuard aGuard (maMutex); OSL_ASSERT(eNewRequestClass>=MIN__CLASS && eNewRequestClass<=MAX__CLASS); Container::const_iterator iRequest ( ::std::find_if ( mpRequestQueue->begin(), mpRequestQueue->end(), Request::DataComparator(aKey))); if (iRequest!=mpRequestQueue->end() && iRequest->meClass!=eNewRequestClass) { AddRequest(aKey, eNewRequestClass, true); SSCD_SET_REQUEST_CLASS(rRequestData.GetPage(),eNewRequestClass); } } CacheKey RequestQueue::GetFront (void) { ::osl::MutexGuard aGuard (maMutex); if (mpRequestQueue->empty()) throw ::com::sun::star::uno::RuntimeException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "RequestQueue::GetFront(): queue is empty")), NULL); return mpRequestQueue->begin()->maKey; } RequestPriorityClass RequestQueue::GetFrontPriorityClass (void) { ::osl::MutexGuard aGuard (maMutex); if (mpRequestQueue->empty()) throw ::com::sun::star::uno::RuntimeException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "RequestQueue::GetFrontPriorityClass(): queue is empty")), NULL); return mpRequestQueue->begin()->meClass; } void RequestQueue::PopFront (void) { ::osl::MutexGuard aGuard (maMutex); if ( ! mpRequestQueue->empty()) { SSCD_SET_STATUS(maRequestQueue.begin()->mpData->GetPage(),NONE); mpRequestQueue->erase(mpRequestQueue->begin()); // Reset the priority counter if possible. if (mpRequestQueue->empty()) { mnMinimumPriority = 0; mnMaximumPriority = 1; } } } bool RequestQueue::IsEmpty (void) { ::osl::MutexGuard aGuard (maMutex); return mpRequestQueue->empty(); } void RequestQueue::Clear (void) { ::osl::MutexGuard aGuard (maMutex); mpRequestQueue->clear(); mnMinimumPriority = 0; mnMaximumPriority = 1; } ::osl::Mutex& RequestQueue::GetMutex (void) { return maMutex; } } } } // end of namespace ::sd::slidesorter::cache /* vim:set shiftwidth=4 softtabstop=4 expandtab: */