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