1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "SlsRequestQueue.hxx"
22 #include <sal/log.hxx>
24 #include <svx/svdpage.hxx>
29 namespace sd::slidesorter::cache
{
33 /** This class extends the actual request data with additional information
34 that is used by the priority queues.
40 CacheKey aKey
, sal_Int32 nPriority
, RequestPriorityClass eClass
)
41 : maKey(aKey
), mnPriorityInClass(nPriority
), meClass(eClass
)
43 /** Sort requests according to priority classes and then to priorities.
45 class Comparator
{ public:
46 bool operator() (const Request
& rRequest1
, const Request
& rRequest2
)
49 if (rRequest1
.meClass
== rRequest2
.meClass
)
51 if (rRequest1
.mnPriorityInClass
== rRequest2
.mnPriorityInClass
)
53 return rRequest1
.maKey
< rRequest2
.maKey
;
55 return rRequest1
.mnPriorityInClass
> rRequest2
.mnPriorityInClass
;
57 return rRequest1
.meClass
< rRequest2
.meClass
;
60 /** Request data is compared arbitrarily by their addresses in memory.
61 This just establishes an order so that the STL containers are happy.
62 The order is not semantically interpreted.
67 explicit DataComparator (const CacheKey aKey
)
71 bool operator() (const Request
& rRequest
) const
73 return maKey
== rRequest
.maKey
;
80 sal_Int32 mnPriorityInClass
;
81 RequestPriorityClass meClass
;
86 class RequestQueue::Container
93 //===== GenericRequestQueue =================================================
95 RequestQueue::RequestQueue (SharedCacheContext pCacheContext
)
96 : mpRequestQueue(new Container
),
97 mpCacheContext(std::move(pCacheContext
)),
103 RequestQueue::~RequestQueue()
108 void RequestQueue::AddRequest (
110 RequestPriorityClass eRequestClass
)
112 ::osl::MutexGuard
aGuard (maMutex
);
114 assert(eRequestClass
>=MIN_CLASS
&& eRequestClass
<=MAX_CLASS
);
116 // If the request is already a member of the queue then remove it so
117 // that the following insertion will use the new prioritization.
118 #if OSL_DEBUG_LEVEL >=2
123 // The priority of the request inside its priority class is defined by
124 // the page number. This ensures a strict top-to-bottom, left-to-right
126 sal_Int32
nPriority (mpCacheContext
->GetPriority(aKey
));
127 Request
aRequest (aKey
, nPriority
, eRequestClass
);
129 std::pair
<Container::iterator
,bool> ret
= mpRequestQueue
->insert(aRequest
);
130 bool bInserted
= ret
.second
;
134 SdrPage
*pPage
= const_cast<SdrPage
*>(aRequest
.maKey
);
135 pPage
->AddPageUser(*this);
138 #if OSL_DEBUG_LEVEL >=2
139 SAL_INFO("sd.sls", __func__
<< ": " << (bRemoved
?"replaced":"added")
140 << " request for page " << ((aKey
->GetPageNum()-1)/2)
141 << " with priority class " << static_cast<int>(eRequestClass
));
145 void RequestQueue::PageInDestruction(const SdrPage
& rPage
)
147 //remove any requests pending for this page which is going away now
148 RemoveRequest(&rPage
);
151 #if OSL_DEBUG_LEVEL >=2
156 RequestQueue::RemoveRequest(
159 ::osl::MutexGuard
aGuard (maMutex
);
160 #if OSL_DEBUG_LEVEL >=2
161 bool bIsRemoved
= false;
165 Container::const_iterator aRequestIterator
= ::std::find_if (
166 mpRequestQueue
->begin(),
167 mpRequestQueue
->end(),
168 Request::DataComparator(aKey
));
169 if (aRequestIterator
!= mpRequestQueue
->end())
171 if (aRequestIterator
->mnPriorityInClass
== mnMinimumPriority
+1)
173 else if (aRequestIterator
->mnPriorityInClass
== mnMaximumPriority
-1)
176 SdrPage
*pPage
= const_cast<SdrPage
*>(aRequestIterator
->maKey
);
177 pPage
->RemovePageUser(*this);
178 mpRequestQueue
->erase(aRequestIterator
);
179 #if OSL_DEBUG_LEVEL >=2
186 #if OSL_DEBUG_LEVEL >=2
192 void RequestQueue::ChangeClass (
194 RequestPriorityClass eNewRequestClass
)
196 ::osl::MutexGuard
aGuard (maMutex
);
198 assert(eNewRequestClass
>=MIN_CLASS
&& eNewRequestClass
<=MAX_CLASS
);
200 Container::const_iterator
iRequest (
202 mpRequestQueue
->begin(),
203 mpRequestQueue
->end(),
204 Request::DataComparator(aKey
)));
205 if (iRequest
!=mpRequestQueue
->end() && iRequest
->meClass
!=eNewRequestClass
)
207 AddRequest(aKey
, eNewRequestClass
);
211 CacheKey
RequestQueue::GetFront()
213 ::osl::MutexGuard
aGuard (maMutex
);
215 if (mpRequestQueue
->empty())
216 throw css::uno::RuntimeException(u
"RequestQueue::GetFront(): queue is empty"_ustr
,
219 return mpRequestQueue
->begin()->maKey
;
222 RequestPriorityClass
RequestQueue::GetFrontPriorityClass()
224 ::osl::MutexGuard
aGuard (maMutex
);
226 if (mpRequestQueue
->empty())
227 throw css::uno::RuntimeException(u
"RequestQueue::GetFrontPriorityClass(): queue is empty"_ustr
,
230 return mpRequestQueue
->begin()->meClass
;
233 void RequestQueue::PopFront()
235 ::osl::MutexGuard
aGuard (maMutex
);
237 if ( mpRequestQueue
->empty())
240 Container::const_iterator
aIter(mpRequestQueue
->begin());
241 SdrPage
*pPage
= const_cast<SdrPage
*>(aIter
->maKey
);
242 pPage
->RemovePageUser(*this);
243 mpRequestQueue
->erase(aIter
);
245 // Reset the priority counter if possible.
246 if (mpRequestQueue
->empty())
248 mnMinimumPriority
= 0;
249 mnMaximumPriority
= 1;
253 bool RequestQueue::IsEmpty()
255 ::osl::MutexGuard
aGuard (maMutex
);
256 return mpRequestQueue
->empty();
259 void RequestQueue::Clear()
261 ::osl::MutexGuard
aGuard (maMutex
);
263 for (const auto& rItem
: *mpRequestQueue
)
265 SdrPage
*pPage
= const_cast<SdrPage
*>(rItem
.maKey
);
266 pPage
->RemovePageUser(*this);
269 mpRequestQueue
->clear();
270 mnMinimumPriority
= 0;
271 mnMaximumPriority
= 1;
274 } // end of namespace ::sd::slidesorter::cache
276 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */