Files
libreoffice/sd/source/ui/slidesorter/cache/SlsRequestQueue.cxx
2012-04-03 14:49:08 +02:00

286 lines
7.2 KiB
C++

/* -*- 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
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#include "SlsRequestQueue.hxx"
#include <set>
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.
#if OSL_DEBUG_LEVEL >=2
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(aKey,eRequestClass);
#if OSL_DEBUG_LEVEL >=2
SAL_INFO("sd.sls", OSL_THIS_FUNC << ": " << (bRemoved?"replaced":"added")
<< " request for page " << ((aKey->GetPageNum()-1)/2)
<< " with priority class " << static_cast<int>(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(aKey,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(aKey,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: */