LibreOffice Module vcl (master)  1
Manager.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <graphic/Manager.hxx>
21 #include <impgraph.hxx>
22 #include <sal/log.hxx>
23 
24 #include <officecfg/Office/Common.hxx>
25 #include <unotools/configmgr.hxx>
26 
27 using namespace css;
28 
29 namespace vcl::graphic
30 {
31 namespace
32 {
33 void setupConfigurationValuesIfPossible(sal_Int64& rMemoryLimit,
34  std::chrono::seconds& rAllowedIdleTime, bool& bSwapEnabled)
35 {
37  return;
38 
39  try
40  {
41  using officecfg::Office::Common::Cache;
42 
43  rMemoryLimit = Cache::GraphicManager::GraphicMemoryLimit::get();
44  rAllowedIdleTime
45  = std::chrono::seconds(Cache::GraphicManager::GraphicAllowedIdleTime::get());
46  bSwapEnabled = Cache::GraphicManager::GraphicSwappingEnabled::get();
47  }
48  catch (...)
49  {
50  }
51 }
52 }
53 
54 Manager& Manager::get()
55 {
56  static Manager gStaticManager;
57  return gStaticManager;
58 }
59 
60 Manager::Manager()
61  : mnAllowedIdleTime(10)
62  , mbSwapEnabled(true)
63  , mnMemoryLimit(300000000)
64  , mnUsedSize(0)
65  , maSwapOutTimer("graphic::Manager maSwapOutTimer")
66 {
67  setupConfigurationValuesIfPossible(mnMemoryLimit, mnAllowedIdleTime, mbSwapEnabled);
68 
69  if (mbSwapEnabled)
70  {
71  maSwapOutTimer.SetInvokeHandler(LINK(this, Manager, SwapOutTimerHandler));
73  maSwapOutTimer.SetDebugName("graphic::Manager maSwapOutTimer");
75  }
76 }
77 
79 {
80  if (!mbSwapEnabled)
81  return;
82 
83  std::scoped_lock<std::recursive_mutex> aGuard(maMutex);
84 
85  for (ImpGraphic* pEachImpGraphic : m_pImpGraphicList)
86  {
87  if (mnUsedSize < mnMemoryLimit * 0.7)
88  return;
89 
90  sal_Int64 nCurrentGraphicSize = getGraphicSizeBytes(pEachImpGraphic);
91  if (!pEachImpGraphic->ImplIsSwapOut() && nCurrentGraphicSize > 1000000)
92  {
93  if (!pEachImpGraphic->mpContext)
94  {
95  auto aCurrent = std::chrono::high_resolution_clock::now();
96  auto aDeltaTime = aCurrent - pEachImpGraphic->maLastUsed;
97  auto aSeconds = std::chrono::duration_cast<std::chrono::seconds>(aDeltaTime);
98 
99  if (aSeconds > mnAllowedIdleTime)
100  pEachImpGraphic->ImplSwapOut();
101  }
102  }
103  }
104 }
105 
106 sal_Int64 Manager::getGraphicSizeBytes(const ImpGraphic* pImpGraphic)
107 {
108  if (!pImpGraphic->isAvailable())
109  return 0;
110  return pImpGraphic->ImplGetSizeBytes();
111 }
112 
113 IMPL_LINK(Manager, SwapOutTimerHandler, Timer*, pTimer, void)
114 {
115  std::scoped_lock<std::recursive_mutex> aGuard(maMutex);
116 
117  pTimer->Stop();
118  reduceGraphicMemory();
119  pTimer->Start();
120 }
121 
122 void Manager::registerGraphic(const std::shared_ptr<ImpGraphic>& pImpGraphic,
123  OUString const& /*rsContext*/)
124 {
125  std::scoped_lock<std::recursive_mutex> aGuard(maMutex);
126 
127  // make some space first
130 
131  // Insert and update the used size (bytes)
132  mnUsedSize += getGraphicSizeBytes(pImpGraphic.get());
133  m_pImpGraphicList.insert(pImpGraphic.get());
134 
135  // calculate size of the graphic set
136  sal_Int64 calculatedSize = 0;
137  for (ImpGraphic* pEachImpGraphic : m_pImpGraphicList)
138  {
139  if (!pEachImpGraphic->ImplIsSwapOut())
140  {
141  calculatedSize += getGraphicSizeBytes(pEachImpGraphic);
142  }
143  }
144 
145  if (calculatedSize != mnUsedSize)
146  {
147  SAL_INFO_IF(calculatedSize != mnUsedSize, "vcl.gdi",
148  "Calculated size mismatch. Variable size is '"
149  << mnUsedSize << "' but calculated size is '" << calculatedSize << "'");
150  mnUsedSize = calculatedSize;
151  }
152 }
153 
155 {
156  std::scoped_lock<std::recursive_mutex> aGuard(maMutex);
157 
158  mnUsedSize -= getGraphicSizeBytes(pImpGraphic);
159  m_pImpGraphicList.erase(pImpGraphic);
160 }
161 
162 std::shared_ptr<ImpGraphic> Manager::copy(std::shared_ptr<ImpGraphic> const& rImpGraphicPtr)
163 {
164  auto pReturn = std::make_shared<ImpGraphic>(*rImpGraphicPtr);
165  registerGraphic(pReturn, "Copy");
166  return pReturn;
167 }
168 
169 std::shared_ptr<ImpGraphic> Manager::newInstance()
170 {
171  auto pReturn = std::make_shared<ImpGraphic>();
172  registerGraphic(pReturn, "Empty");
173  return pReturn;
174 }
175 
176 std::shared_ptr<ImpGraphic> Manager::newInstance(const Bitmap& rBitmap)
177 {
178  auto pReturn = std::make_shared<ImpGraphic>(rBitmap);
179  registerGraphic(pReturn, "Bitmap");
180  return pReturn;
181 }
182 
183 std::shared_ptr<ImpGraphic> Manager::newInstance(const BitmapEx& rBitmapEx)
184 {
185  auto pReturn = std::make_shared<ImpGraphic>(rBitmapEx);
186  registerGraphic(pReturn, "BitmapEx");
187  return pReturn;
188 }
189 
190 std::shared_ptr<ImpGraphic> Manager::newInstance(const Animation& rAnimation)
191 {
192  auto pReturn = std::make_shared<ImpGraphic>(rAnimation);
193  registerGraphic(pReturn, "Animation");
194  return pReturn;
195 }
196 
197 std::shared_ptr<ImpGraphic> Manager::newInstance(const VectorGraphicDataPtr& rVectorGraphicDataPtr)
198 {
199  auto pReturn = std::make_shared<ImpGraphic>(rVectorGraphicDataPtr);
200  registerGraphic(pReturn, "VectorGraphic");
201  return pReturn;
202 }
203 
204 std::shared_ptr<ImpGraphic> Manager::newInstance(const GDIMetaFile& rMetaFile)
205 {
206  auto pReturn = std::make_shared<ImpGraphic>(rMetaFile);
207  registerGraphic(pReturn, "Metafile");
208  return pReturn;
209 }
210 
211 std::shared_ptr<ImpGraphic> Manager::newInstance(const GraphicExternalLink& rGraphicLink)
212 {
213  auto pReturn = std::make_shared<ImpGraphic>(rGraphicLink);
214  registerGraphic(pReturn, "GraphicExternalLink");
215  return pReturn;
216 }
217 
218 void Manager::swappedIn(const ImpGraphic* pImpGraphic)
219 {
220  std::scoped_lock<std::recursive_mutex> aGuard(maMutex);
221 
222  mnUsedSize += getGraphicSizeBytes(pImpGraphic);
223 }
224 
225 void Manager::swappedOut(const ImpGraphic* pImpGraphic)
226 {
227  std::scoped_lock<std::recursive_mutex> aGuard(maMutex);
228 
229  mnUsedSize -= getGraphicSizeBytes(pImpGraphic);
230 }
231 
232 void Manager::changeExisting(const ImpGraphic* pImpGraphic, sal_Int64 nOldSizeBytes)
233 {
234  std::scoped_lock<std::recursive_mutex> aGuard(maMutex);
235 
236  mnUsedSize -= nOldSizeBytes;
237  mnUsedSize += getGraphicSizeBytes(pImpGraphic);
238 }
239 } // end vcl::graphic
240 
241 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
o3tl::sorted_vector< ImpGraphic * > m_pImpGraphicList
Definition: Manager.hxx:36
static sal_Int64 getGraphicSizeBytes(const ImpGraphic *pImpGraphic)
Definition: Manager.cxx:106
void unregisterGraphic(ImpGraphic *pImpGraphic)
Definition: Manager.cxx:154
#define SAL_INFO_IF(condition, area, stream)
void reduceGraphicMemory()
Definition: Manager.cxx:78
std::shared_ptr< ImpGraphic > copy(std::shared_ptr< ImpGraphic > const &pImpGraphic)
Definition: Manager.cxx:162
std::recursive_mutex maMutex
Definition: Manager.hxx:35
static bool IsFuzzing()
IMPL_LINK(Manager, SwapOutTimerHandler, Timer *, pTimer, void)
Definition: Manager.cxx:113
::osl::Mutex maMutex
std::chrono::seconds mnAllowedIdleTime
Definition: Manager.hxx:37
void SetDebugName(const char *pDebugName)
Definition: task.hxx:81
sal_Int64 mnUsedSize
Definition: Manager.hxx:40
std::shared_ptr< ImpGraphic > newInstance()
Definition: Manager.cxx:169
void changeExisting(const ImpGraphic *pImpGraphic, sal_Int64 nOldSize)
Definition: Manager.cxx:232
virtual void Start() override
Activates the timer task.
Definition: timer.cxx:83
void SetTimeout(sal_uInt64 nTimeoutMs)
Definition: timer.cxx:89
void registerGraphic(const std::shared_ptr< ImpGraphic > &rImpGraphic, OUString const &rsContext)
Definition: Manager.cxx:122
std::shared_ptr< VectorGraphicData > VectorGraphicDataPtr
void swappedIn(const ImpGraphic *pImpGraphic)
Definition: Manager.cxx:218
sal_uLong ImplGetSizeBytes() const
Definition: impgraph.cxx:931
void SetInvokeHandler(const Link< Timer *, void > &rLink)
Definition: timer.hxx:56
void swappedOut(const ImpGraphic *pImpGraphic)
Definition: Manager.cxx:225
bool isAvailable() const
Definition: impgraph.cxx:505
sal_Int64 mnMemoryLimit
Definition: Manager.hxx:39
Definition: timer.hxx:26
std::pair< const_iterator, bool > insert(Value &&x)
size_type erase(const Value &x)