Line data Source code
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 : #ifndef INCLUDED_SW_SOURCE_CORE_INC_SWCACHE_HXX
20 : #define INCLUDED_SW_SOURCE_CORE_INC_SWCACHE_HXX
21 :
22 : /**
23 : * Here, we manage pointers in a simple PtrArray to objects.
24 : * These objects are created (using new) in cache access classes; they are
25 : * destroyed by the cache.
26 : *
27 : * One can access these objects by array index or by searching in the array
28 : * If you access it by index, managing the index is the responsibility of
29 : * the cache user.
30 : *
31 : * The cached objects are derrived from the base class SwCacheObj.
32 : * In it, the cache objects are doubly-linked which allows for the use of
33 : * an LRU algorithm.
34 : *
35 : * The LRU algorithm can be changed in the base class, by setting a virtual
36 : * First Pointer. It can be set to the first real one plus an offset.
37 : * By doing so we can protect the start area of the cache and make sure we
38 : * don't mess up the cache during some special operations.
39 : * E.g.: the Idle Handler should not destroy the cache for the visible area.
40 : *
41 : * The cache can be grown and shrunk in size.
42 : * E.g.: The cache for FormatInfo is grown for every new Shell and shrunk
43 : * when destroying them.
44 : */
45 :
46 : #include <vector>
47 :
48 : #include <rtl/ustring.hxx>
49 :
50 : class SwCacheObj;
51 :
52 : typedef std::vector<SwCacheObj*> SwCacheObjArr;
53 : class SwCache
54 : {
55 : SwCacheObjArr m_aCacheObjects;
56 : std::vector<sal_uInt16> aFreePositions; /// Free positions for the Insert if the maximum has not been reached
57 : /// Every time an object is deregistered, its position is added here
58 : SwCacheObj *pRealFirst; /// _ALWAYS_ the real first LRU
59 : SwCacheObj *pFirst; /// The virtual first
60 : SwCacheObj *pLast;
61 :
62 : sal_uInt16 nCurMax; // Maximum of accepted objects
63 :
64 : void DeleteObj( SwCacheObj *pObj );
65 :
66 : #ifdef DBG_UTIL
67 : OString m_aName;
68 : long m_nAppend; /// number of entries appended
69 : long m_nInsertFree; /// number of entries inserted on freed position
70 : long m_nReplace; /// number of LRU replacements
71 : long m_nGetSuccess;
72 : long m_nGetFail;
73 : long m_nToTop; /// number of reordering (LRU)
74 : long m_nDelete; /// number of explicit deletes
75 : long m_nGetSeek; /// number of gets without index
76 : long m_nAverageSeekCnt; /// number of seeks for all gets without index
77 : long m_nFlushCnt; /// number of flush calls
78 : long m_nFlushedObjects;
79 : long m_nIncreaseMax; /// number of cache size increases
80 : long m_nDecreaseMax; /// number of cache size decreases
81 :
82 : void Check();
83 : #endif
84 :
85 : public:
86 :
87 : // Only add sal_uInt8!!!
88 : #ifdef DBG_UTIL
89 : SwCache( const sal_uInt16 nInitSize, const OString &rNm );
90 : #else
91 : SwCache( const sal_uInt16 nInitSize );
92 : #endif
93 : /// The dtor will free all objects still in the vector
94 : ~SwCache();
95 :
96 : void Flush( const sal_uInt8 nPercent = 100 );
97 :
98 : //bToTop == false -> No LRU resorting!
99 : SwCacheObj *Get( const void *pOwner, const bool bToTop = true );
100 : SwCacheObj *Get( const void *pOwner, const sal_uInt16 nIndex,
101 : const bool bToTop = true );
102 : void ToTop( SwCacheObj *pObj );
103 :
104 : bool Insert( SwCacheObj *pNew );
105 : void Delete( const void *pOwner );
106 : // void Delete( const void *pOwner, const sal_uInt16 nIndex );
107 :
108 : void SetLRUOfst( const sal_uInt16 nOfst ); /// nOfst determines how many are not to be touched
109 5365 : void ResetLRUOfst() { pFirst = pRealFirst; }
110 :
111 : inline void IncreaseMax( const sal_uInt16 nAdd );
112 : inline void DecreaseMax( const sal_uInt16 nSub );
113 15999 : sal_uInt16 GetCurMax() const { return nCurMax; }
114 287956 : inline SwCacheObj *First() { return pRealFirst; }
115 : inline SwCacheObj *Last() { return pLast; }
116 : inline SwCacheObj *Next( SwCacheObj *pCacheObj);
117 : inline SwCacheObj* operator[](sal_uInt16 nIndex) { return m_aCacheObjects[nIndex]; }
118 : inline sal_uInt16 size() { return m_aCacheObjects.size(); }
119 : };
120 :
121 : /// Safely manipulate the cache
122 : class SwSaveSetLRUOfst
123 : {
124 : SwCache &rCache;
125 : public:
126 5365 : SwSaveSetLRUOfst( SwCache &rC, const sal_uInt16 nOfst )
127 5365 : : rCache( rC ) { rCache.SetLRUOfst( nOfst ); }
128 :
129 5365 : ~SwSaveSetLRUOfst() { rCache.ResetLRUOfst(); }
130 : };
131 :
132 : /**
133 : * The Cache object base class
134 : * Users of the Cache must derrive a class from the SwCacheObj and store
135 : * their payload there
136 : */
137 : class SwCacheObj
138 : {
139 : friend class SwCache; /// Can do everything
140 :
141 : SwCacheObj *pNext; /// For the LRU chaining
142 : SwCacheObj *pPrev;
143 :
144 : sal_uInt16 nCachePos; /// Position in the Cache array
145 :
146 : sal_uInt8 nLock;
147 :
148 9196521 : inline SwCacheObj *GetNext() { return pNext; }
149 2440035 : inline SwCacheObj *GetPrev() { return pPrev; }
150 1638073 : inline void SetNext( SwCacheObj *pNew ) { pNext = pNew; }
151 2077843 : inline void SetPrev( SwCacheObj *pNew ) { pPrev = pNew; }
152 :
153 225926 : inline void SetCachePos( const sal_uInt16 nNew ) { nCachePos = nNew; }
154 :
155 : protected:
156 : const void *pOwner;
157 : inline void SetOwner( const void *pNew ) { pOwner = pNew; }
158 :
159 : public:
160 :
161 : SwCacheObj( const void *pOwner );
162 : virtual ~SwCacheObj();
163 :
164 495831 : inline const void *GetOwner() const { return pOwner; }
165 : inline bool IsOwner( const void *pNew ) const;
166 :
167 622777 : inline sal_uInt16 GetCachePos() const { return nCachePos; }
168 : inline void Invalidate() { pOwner = 0; }
169 :
170 232127 : inline bool IsLocked() const { return 0 != nLock; }
171 :
172 : #ifdef DBG_UTIL
173 : void Lock();
174 : void Unlock();
175 : #else
176 4126989 : inline void Lock() { ++nLock; }
177 4126905 : inline void Unlock() { --nLock; }
178 : #endif
179 :
180 : SwCacheObj *Next() { return pNext; }
181 : SwCacheObj *Prev() { return pPrev; }
182 :
183 : };
184 :
185 : /**
186 : * Access class for the Cache
187 : *
188 : * The Cache object is created in the ctor.
189 : * If the Cache does not return one, the member is set to 0 and one is
190 : * created on the Get() and added to the Cache (if possible).
191 : * Cache users must derrive a class from SwCacheAccess in order to
192 : * guarantee type safety. The base class should always be called for the
193 : * Get(). A derrived Get() should only ever guarantee type safety.
194 : * Cache objects are always locked for the instance's life time.
195 : */
196 : class SwCacheAccess
197 : {
198 : SwCache &rCache;
199 :
200 : void _Get();
201 :
202 : protected:
203 : SwCacheObj *pObj;
204 : const void *pOwner; /// Can be use in NewObj
205 :
206 : virtual SwCacheObj *NewObj() = 0;
207 :
208 : inline SwCacheObj *Get();
209 :
210 : inline SwCacheAccess( SwCache &rCache, const void *pOwner, bool bSeek = true );
211 : inline SwCacheAccess( SwCache &rCache, const void *pOwner, const sal_uInt16 nIndex );
212 :
213 : public:
214 : virtual ~SwCacheAccess();
215 :
216 : virtual bool IsAvailable() const;
217 :
218 : /// Shorthand for those who know, that they did not overload isAvailable()
219 1902885 : bool IsAvail() const { return pObj != 0; }
220 : };
221 :
222 5318 : inline void SwCache::IncreaseMax( const sal_uInt16 nAdd )
223 : {
224 5318 : nCurMax = nCurMax + sal::static_int_cast< sal_uInt16 >(nAdd);
225 : #ifdef DBG_UTIL
226 : ++m_nIncreaseMax;
227 : #endif
228 5318 : }
229 5316 : inline void SwCache::DecreaseMax( const sal_uInt16 nSub )
230 : {
231 5316 : if ( nCurMax > nSub )
232 5316 : nCurMax = nCurMax - sal::static_int_cast< sal_uInt16 >(nSub);
233 : #ifdef DBG_UTIL
234 : ++m_nDecreaseMax;
235 : #endif
236 5316 : }
237 :
238 8753689 : inline bool SwCacheObj::IsOwner( const void *pNew ) const
239 : {
240 8753689 : return pOwner && pOwner == pNew;
241 : }
242 :
243 288343 : inline SwCacheObj *SwCache::Next( SwCacheObj *pCacheObj)
244 : {
245 288343 : if ( pCacheObj )
246 288343 : return pCacheObj->GetNext();
247 : else
248 0 : return NULL;
249 : }
250 :
251 1072367 : inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn, bool bSeek ) :
252 : rCache( rC ),
253 : pObj( 0 ),
254 1072367 : pOwner( pOwn )
255 : {
256 1072367 : if ( bSeek && pOwner && 0 != (pObj = rCache.Get( pOwner )) )
257 904682 : pObj->Lock();
258 1072367 : }
259 :
260 2109150 : inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn,
261 : const sal_uInt16 nIndex ) :
262 : rCache( rC ),
263 : pObj( 0 ),
264 2109150 : pOwner( pOwn )
265 : {
266 2109150 : if ( pOwner && 0 != (pObj = rCache.Get( pOwner, nIndex )) )
267 1797472 : pObj->Lock();
268 2109150 : }
269 :
270 4032215 : inline SwCacheObj *SwCacheAccess::Get()
271 : {
272 4032215 : if ( !pObj )
273 223572 : _Get();
274 4032215 : return pObj;
275 : }
276 :
277 : #endif
278 :
279 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|