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 _SWCACHE_HXX
20 : #define _SWCACHE_HXX
21 :
22 : /*
23 : * Es werden Pointer auf Objekte verwaltet. Diese werden in einem einfachen
24 : * PtrArray verwaltet.
25 : * Angelegt (new) werden die Objekte von Cache-Zugriffsklassen, zuerstoert
26 : * werden die Objekte vom Cache.
27 : *
28 : * Auf die Objekte kann wahlweise per Index in das Array oder per Suche
29 : * zugegriffen werden. Soll per Index zugegriffen werden, so obliegt die
30 : * Verwaltung des Index dem Anwender des Cache.
31 : *
32 : * Fuer die verwalteten Cache-Objekte gibt es eine Basisklasse, von dieser
33 : * sind spezifische Klassen abzuleiten.
34 : * In der Basisklasse werden die Cache-Objekte eines Cache doppelt verkettet,
35 : * das ermoeglich die Implementierung eines LRU-Algorithmus.
36 : *
37 : * Der LRU kann in der Cache-Basisklasse manipuliert werden, indem ein
38 : * virtueller First-Pointer gesetzt wird. Dieser kann auf den echten ersten
39 : * plus einem Ofst gesetzt werden. Dadurch kann man den Anfangsbereich des
40 : * Cache sichern und so dafuer sorgen, dass man waehrend bestimmter
41 : * Operationen nicht den Cache versaut. Beispiel: Der Idle-Handler sollte nicht
42 : * den Cache fuer den sichtbaren Bereich vernichten.
43 : *
44 : * Der Cache kann in der Groesse erweitert und wieder verkleinert werden.
45 : * Beispiel: Fuer jede neue Shell wird der Cache fuer FormatInfo vergrossert
46 : * und beim Destruieren der Shell wieder verkleinert.
47 : *
48 : */
49 :
50 : #include <vector>
51 :
52 : #include <rtl/ustring.hxx>
53 :
54 : class SwCacheObj;
55 :
56 : typedef std::vector<SwCacheObj*> SwCacheObjArr;
57 : class SwCache
58 : {
59 : SwCacheObjArr m_aCacheObjects;
60 : std::vector<sal_uInt16> aFreePositions; //Freie Positionen fuer das Insert wenn
61 : //die Maximalgrenze nicht erreicht ist.
62 : //Immer wenn ein Objekt ausgetragen wird,
63 : //so wird seine Position hier eingetragen.
64 :
65 : SwCacheObj *pRealFirst; //_immer_ der echte LRU-erste
66 : SwCacheObj *pFirst; //der virtuelle erste.
67 : SwCacheObj *pLast;
68 :
69 : sal_uInt16 nCurMax; //Mehr werden nicht aufgenommen.
70 :
71 :
72 : void DeleteObj( SwCacheObj *pObj );
73 :
74 : #ifdef DBG_UTIL
75 : rtl::OString m_aName;
76 : long m_nAppend; /// number of entries appended
77 : long m_nInsertFree; /// number of entries inserted on freed position
78 : long m_nReplace; /// number of LRU replacements
79 : long m_nGetSuccess;
80 : long m_nGetFail;
81 : long m_nToTop; /// number of reordering (LRU)
82 : long m_nDelete; /// number of explicit deletes
83 : long m_nGetSeek; /// number of gets without index
84 : long m_nAverageSeekCnt; /// number of seeks for all gets without index
85 : long m_nFlushCnt; /// number of flush calls
86 : long m_nFlushedObjects;
87 : long m_nIncreaseMax; /// number of cache size increases
88 : long m_nDecreaseMax; /// number of cache size decreases
89 :
90 : void Check();
91 : #endif
92 :
93 : public:
94 :
95 : //nur sal_uInt8 hineinstecken!!!
96 : #ifdef DBG_UTIL
97 : SwCache( const sal_uInt16 nInitSize, const rtl::OString &rNm );
98 : #else
99 : SwCache( const sal_uInt16 nInitSize );
100 : #endif
101 : // the destructor will free all objects still in the vector
102 : ~SwCache();
103 :
104 : void Flush( const sal_uInt8 nPercent = 100 );
105 :
106 : //bToTop == sal_False -> Keine LRU-Umsortierung!
107 : SwCacheObj *Get( const void *pOwner, const sal_Bool bToTop = sal_True );
108 : SwCacheObj *Get( const void *pOwner, const sal_uInt16 nIndex,
109 : const sal_Bool bToTop = sal_True );
110 : void ToTop( SwCacheObj *pObj );
111 :
112 : sal_Bool Insert( SwCacheObj *pNew );
113 : void Delete( const void *pOwner );
114 : // void Delete( const void *pOwner, const sal_uInt16 nIndex );
115 :
116 : void SetLRUOfst( const sal_uInt16 nOfst ); //nOfst sagt wieviele unangetastet
117 : //bleiben sollen.
118 432 : void ResetLRUOfst() { pFirst = pRealFirst; }
119 :
120 : inline void IncreaseMax( const sal_uInt16 nAdd );
121 : inline void DecreaseMax( const sal_uInt16 nSub );
122 735 : sal_uInt16 GetCurMax() const { return nCurMax; }
123 2053 : inline SwCacheObj *First() { return pRealFirst; }
124 : inline SwCacheObj *Last() { return pLast; }
125 : inline SwCacheObj *Next( SwCacheObj *pCacheObj);
126 : inline SwCacheObj* operator[](sal_uInt16 nIndex) { return m_aCacheObjects[nIndex]; }
127 : inline sal_uInt16 size() { return m_aCacheObjects.size(); }
128 : };
129 :
130 : //Cache-Manipulation auf die sichere Art.
131 : class SwSaveSetLRUOfst
132 : {
133 : SwCache &rCache;
134 : public:
135 432 : SwSaveSetLRUOfst( SwCache &rC, const sal_uInt16 nOfst )
136 432 : : rCache( rC ) { rCache.SetLRUOfst( nOfst ); }
137 :
138 432 : ~SwSaveSetLRUOfst() { rCache.ResetLRUOfst(); }
139 : };
140 :
141 : //Das allgemeine CacheObjekt. Anwender des Cache muessen eine Klasse vom
142 : //CacheObjekt ableiten und dort die Nutzdaten unterbringen.
143 :
144 : class SwCacheObj
145 : {
146 : friend class SwCache; //Der darf alles
147 :
148 : SwCacheObj *pNext; //Fuer die LRU-Verkettung.
149 : SwCacheObj *pPrev;
150 :
151 : sal_uInt16 nCachePos; //Position im Cache-Array.
152 :
153 : sal_uInt8 nLock;
154 :
155 74167 : inline SwCacheObj *GetNext() { return pNext; }
156 26686 : inline SwCacheObj *GetPrev() { return pPrev; }
157 19208 : inline void SetNext( SwCacheObj *pNew ) { pNext = pNew; }
158 24483 : inline void SetPrev( SwCacheObj *pNew ) { pPrev = pNew; }
159 :
160 3746 : inline void SetCachePos( const sal_uInt16 nNew ) { nCachePos = nNew; }
161 :
162 : protected:
163 : const void *pOwner;
164 : inline void SetOwner( const void *pNew ) { pOwner = pNew; }
165 :
166 : public:
167 :
168 : SwCacheObj( const void *pOwner );
169 : virtual ~SwCacheObj();
170 :
171 3188 : inline const void *GetOwner() const { return pOwner; }
172 : inline sal_Bool IsOwner( const void *pNew ) const;
173 :
174 6066 : inline sal_uInt16 GetCachePos() const { return nCachePos; }
175 : inline void Invalidate() { pOwner = 0; }
176 :
177 2141 : inline sal_Bool IsLocked() const { return 0 != nLock; }
178 :
179 : #ifdef DBG_UTIL
180 : void Lock();
181 : void Unlock();
182 : #else
183 33648 : inline void Lock() { ++nLock; }
184 33639 : inline void Unlock() { --nLock; }
185 : #endif
186 :
187 : SwCacheObj *Next() { return pNext; }
188 : SwCacheObj *Prev() { return pPrev; }
189 :
190 : };
191 :
192 : //Zugriffsklasse fuer den Cache. Im CTor wird das CacheObjekt erzeugt.
193 : //Wenn der Cache keines herausrueckt wird der Member zunaechst auf 0 gesetzt.
194 : //Beim Get wird dann eines erzeugt und, falls moeglich, in den Cache
195 : //eingetragen.
196 : //Anwender der des Cache muessen eine Klasse vom Access ableiten um
197 : //fuer Typsicherheit zu sorgen, die Basisklasse sollte fuer das Get aber immer
198 : //gerufen werden, ein Abgeleitetes Get sollte nur der Typsicherheit dienen.
199 : //Cache-Objekte werden stets gelockt solange die Instanz lebt.
200 :
201 : class SwCacheAccess
202 : {
203 : SwCache &rCache;
204 :
205 : void _Get();
206 :
207 : protected:
208 : SwCacheObj *pObj;
209 : const void *pOwner; //Kann ggf. in NewObj benutzt werden.
210 :
211 : virtual SwCacheObj *NewObj() = 0;
212 :
213 : inline SwCacheObj *Get();
214 :
215 : inline SwCacheAccess( SwCache &rCache, const void *pOwner, sal_Bool bSeek = sal_True );
216 : inline SwCacheAccess( SwCache &rCache, const void *pOwner, const sal_uInt16 nIndex );
217 :
218 : public:
219 : virtual ~SwCacheAccess();
220 :
221 : virtual sal_Bool IsAvailable() const;
222 :
223 : //Abkuerzung fuer diejenigen, die wissen, das die Ableitung das IsAvailable
224 : //nicht ueberladen haben.
225 10361 : sal_Bool IsAvail() const { return pObj != 0; }
226 : };
227 :
228 163 : inline void SwCache::IncreaseMax( const sal_uInt16 nAdd )
229 : {
230 163 : nCurMax = nCurMax + sal::static_int_cast< sal_uInt16 >(nAdd);
231 : #ifdef DBG_UTIL
232 : ++m_nIncreaseMax;
233 : #endif
234 163 : }
235 65 : inline void SwCache::DecreaseMax( const sal_uInt16 nSub )
236 : {
237 65 : if ( nCurMax > nSub )
238 65 : nCurMax = nCurMax - sal::static_int_cast< sal_uInt16 >(nSub);
239 : #ifdef DBG_UTIL
240 : ++m_nDecreaseMax;
241 : #endif
242 65 : }
243 :
244 96359 : inline sal_Bool SwCacheObj::IsOwner( const void *pNew ) const
245 : {
246 96359 : return pOwner && pOwner == pNew;
247 : }
248 :
249 1777 : inline SwCacheObj *SwCache::Next( SwCacheObj *pCacheObj)
250 : {
251 1777 : if ( pCacheObj )
252 1777 : return pCacheObj->GetNext();
253 : else
254 0 : return NULL;
255 : }
256 :
257 15749 : inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn, sal_Bool bSeek ) :
258 : rCache( rC ),
259 : pObj( 0 ),
260 15749 : pOwner( pOwn )
261 : {
262 15749 : if ( bSeek && pOwner && 0 != (pObj = rCache.Get( pOwner )) )
263 12953 : pObj->Lock();
264 15749 : }
265 :
266 12132 : inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn,
267 : const sal_uInt16 nIndex ) :
268 : rCache( rC ),
269 : pObj( 0 ),
270 12132 : pOwner( pOwn )
271 : {
272 12132 : if ( pOwner && 0 != (pObj = rCache.Get( pOwner, nIndex )) )
273 10146 : pObj->Lock();
274 12132 : }
275 :
276 34956 : inline SwCacheObj *SwCacheAccess::Get()
277 : {
278 34956 : if ( !pObj )
279 3716 : _Get();
280 34956 : return pObj;
281 : }
282 :
283 :
284 : #endif
285 :
286 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|