xref: /trunk/main/sw/source/core/inc/swcache.hxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #ifndef _SWCACHE_HXX
28 #define _SWCACHE_HXX
29 
30 
31 
32 /*
33  * Es werden Pointer auf Objekte verwaltet. Diese werden in einem einfachen
34  * PtrArray verwaltet.
35  * Angelegt (new) werden die Objekte von Cache-Zugriffsklassen, zuerstoert
36  * werden die Objekte vom Cache.
37  *
38  * Auf die Objekte kann wahlweise per Index in das Array oder per Suche
39  * zugegriffen werden. Soll per Index zugegriffen werden, so obliegt die
40  * Verwaltung des Index dem Anwender des Cache.
41  *
42  * Fuer die verwalteten Cache-Objekte gibt es eine Basisklasse, von dieser
43  * sind spezifische Klassen abzuleiten.
44  * In der Basisklasse werden die Cache-Objekte eines Cache doppelt verkettet,
45  * das ermoeglich die Implementierung eines LRU-Algorithmus.
46  *
47  * Der LRU kann in der Cache-Basisklasse manipuliert werden, indem ein
48  * virtueller First-Pointer gesetzt wird. Dieser kann auf den echten ersten
49  * plus einem Ofst gesetzt werden. Dadurch kann man den Anfangsbereich des
50  * Cache sichern und so dafuer sorgen, dass man waehrend bestimmter
51  * Operationen nicht den Cache versaut. Beispiel: Der Idle-Handler sollte nicht
52  * den Cache fuer den sichtbaren Bereich vernichten.
53  *
54  * Der Cache kann in der Groesse erweitert und wieder verkleinert werden.
55  * Beispiel: Fuer jede neue Shell wird der Cache fuer FormatInfo vergrossert
56  * und beim Destruieren der Shell wieder verkleinert.
57  *
58  */
59 
60 #ifdef DBG_UTIL
61 #ifndef _STRING_HXX //autogen
62 #include <tools/string.hxx>
63 #endif
64 #endif
65 
66 #ifndef _SVSTDARR_HXX
67 #define _SVSTDARR_USHORTS
68 #include <svl/svstdarr.hxx>
69 #endif
70 
71 class SwCacheObj;
72 
73 SV_DECL_PTRARR_DEL(SwCacheObjArr,SwCacheObj*,1,1)
74 
75 class SwCache : public SwCacheObjArr
76 {
77     SvUShorts aFreePositions;       //Freie Positionen fuer das Insert wenn
78                                     //die Maximalgrenze nicht erreicht ist.
79                                     //Immer wenn ein Objekt ausgetragen wird,
80                                     //so wird seine Position hier eingetragen.
81 
82     SwCacheObj *pRealFirst;         //_immer_ der echte LRU-erste
83     SwCacheObj *pFirst;             //der virtuelle erste.
84     SwCacheObj *pLast;
85 
86     const sal_uInt16 nMax;              //Mehr sollen nicht aufgenommen werden,
87                                     //der Cache kann aber dynamisch um jeweils
88                                     //nMax vergroessert werden.
89           sal_uInt16 nCurMax;           //Mehr werden nicht aufgenommen.
90 
91 
92     void DeleteObj( SwCacheObj *pObj );
93 
94 #ifdef DBG_UTIL
95     ByteString aName;
96     long nAppend;           //Anzahl der Eintragungen durch Erweiterung.
97     long nInsertFree;       //Anzahl der Eintragungen auf freie Plaetze.
98     long nReplace;          //Anzahl der Ersetzungen durch ein neues Objekt
99     long nGetSuccess;       //Anzahl der Erfolgreichen Get's
100     long nGetFail;          //Anzahl der nicht Erfolgreichen Get's
101     long nToTop;            //Anzahl der Umsortierungen (LRU)
102     long nDelete;           //Anzahl der Loeschungen (von Aussen)
103     long nGetSeek;          //Anzahl der Get's ohne Index
104     long nAverageSeekCnt;   //Anzahl der Seek's fuer alle Get's ohne Index
105     long nFlushCnt;         //Anzahl von Flush-Aufrufen.
106     long nFlushedObjects;   //Anzahl der wg. Flush vernichteten Objekte
107     long nIncreaseMax;      //Anzahl Cache-Erweiterungen
108     long nDecreaseMax;      //Anzahl Cache-Verkleinerungen
109 
110     void Check();           //Wird bei swcache.cxx mit DEBUG aktiv!
111 #endif
112 
113 public:
114 
115     //nur sal_uInt8 hineinstecken!!!
116 #ifdef DBG_UTIL
117     SwCache( const sal_uInt16 nInitSize, const sal_uInt16 nGrowSize,
118             const ByteString &rNm );
119     ~SwCache();
120 #else
121     SwCache( const sal_uInt16 nInitSize, const sal_uInt16 nGrowSize );
122 #endif
123 
124     void Flush( const sal_uInt8 nPercent = 100 );
125 
126     //bToTop == sal_False -> Keine LRU-Umsortierung!
127     SwCacheObj *Get( const void *pOwner, const sal_Bool bToTop = sal_True );
128     SwCacheObj *Get( const void *pOwner, const sal_uInt16 nIndex,
129                      const sal_Bool bToTop = sal_True );
130     void ToTop( SwCacheObj *pObj );
131 
132     sal_Bool Insert( SwCacheObj *pNew );
133     void Delete( const void *pOwner );
134 //  void Delete( const void *pOwner, const sal_uInt16 nIndex );
135 
136     void SetLRUOfst( const sal_uInt16 nOfst );      //nOfst sagt wieviele unangetastet
137                                                 //bleiben sollen.
138     void ResetLRUOfst() { pFirst = pRealFirst; }
139 
140     inline void IncreaseMax( const sal_uInt16 nAdd );
141     inline void DecreaseMax( const sal_uInt16 nSub );
142     sal_uInt16 GetCurMax() const { return nCurMax; }
143     inline SwCacheObj *First() { return pRealFirst; }
144     inline SwCacheObj *Last()  { return pLast; }
145     inline SwCacheObj *Next( SwCacheObj *pCacheObj);
146 };
147 
148 //Cache-Manipulation auf die sichere Art.
149 class SwSaveSetLRUOfst
150 {
151     SwCache &rCache;
152 public:
153     SwSaveSetLRUOfst( SwCache &rC, const sal_uInt16 nOfst )
154         : rCache( rC )          { rCache.SetLRUOfst( nOfst );  }
155 
156     ~SwSaveSetLRUOfst()         { rCache.ResetLRUOfst(); }
157 };
158 
159 //Das allgemeine CacheObjekt. Anwender des Cache muessen eine Klasse vom
160 //CacheObjekt ableiten und dort die Nutzdaten unterbringen.
161 
162 class SwCacheObj
163 {
164     friend class SwCache;   //Der darf alles
165 
166     SwCacheObj *pNext;      //Fuer die LRU-Verkettung.
167     SwCacheObj *pPrev;
168 
169     sal_uInt16 nCachePos;       //Position im Cache-Array.
170 
171     sal_uInt8       nLock;
172 
173     inline SwCacheObj *GetNext() { return pNext; }
174     inline SwCacheObj *GetPrev() { return pPrev; }
175     inline void SetNext( SwCacheObj *pNew )  { pNext = pNew; }
176     inline void SetPrev( SwCacheObj *pNew )  { pPrev = pNew; }
177 
178     inline void   SetCachePos( const sal_uInt16 nNew ) { nCachePos = nNew; }
179 
180 protected:
181     const void *pOwner;
182     inline void SetOwner( const void *pNew ) { pOwner = pNew; }
183 
184 public:
185 
186     SwCacheObj( const void *pOwner );
187     virtual ~SwCacheObj();
188 
189     inline const void *GetOwner() const { return pOwner; }
190     inline sal_Bool IsOwner( const void *pNew ) const;
191 
192     inline sal_uInt16 GetCachePos() const { return nCachePos; }
193     inline void Invalidate()          { pOwner = 0; }
194 
195     inline sal_Bool IsLocked() const { return 0 != nLock; }
196 
197 #ifndef DBG_UTIL
198     inline void Lock() { ++nLock; }
199     inline void Unlock() { --nLock; }
200 #else
201     void Lock();
202     void Unlock();
203 #endif
204 
205     SwCacheObj *Next() { return pNext; }
206     SwCacheObj *Prev() { return pPrev; }
207 
208 };
209 
210 //Zugriffsklasse fuer den Cache. Im CTor wird das CacheObjekt erzeugt.
211 //Wenn der Cache keines herausrueckt wird der Member zunaechst auf 0 gesetzt.
212 //Beim Get wird dann eines erzeugt und, falls moeglich, in den Cache
213 //eingetragen.
214 //Anwender der des Cache muessen eine Klasse vom Access ableiten um
215 //fuer Typsicherheit zu sorgen, die Basisklasse sollte fuer das Get aber immer
216 //gerufen werden, ein Abgeleitetes Get sollte nur der Typsicherheit dienen.
217 //Cache-Objekte werden stets gelockt solange die Instanz lebt.
218 
219 class SwCacheAccess
220 {
221     SwCache &rCache;
222 
223     void _Get();
224 
225 protected:
226     SwCacheObj *pObj;
227     const void *pOwner;     //Kann ggf. in NewObj benutzt werden.
228 
229     virtual SwCacheObj *NewObj() = 0;
230 
231     inline SwCacheObj *Get();
232 
233     inline SwCacheAccess( SwCache &rCache, const void *pOwner, sal_Bool bSeek = sal_True );
234     inline SwCacheAccess( SwCache &rCache, const void *pOwner, const sal_uInt16 nIndex );
235 
236 public:
237     virtual ~SwCacheAccess();
238 
239     virtual sal_Bool IsAvailable() const;
240 
241     //Abkuerzung fuer diejenigen, die wissen, das die Ableitung das IsAvailable
242     //nicht ueberladen haben.
243     sal_Bool IsAvail() const { return pObj != 0; }
244 };
245 
246 inline void SwCache::IncreaseMax( const sal_uInt16 nAdd )
247 {
248     nCurMax = nCurMax + sal::static_int_cast< sal_uInt16 >(nAdd);
249 #ifdef DBG_UTIL
250     ++nIncreaseMax;
251 #endif
252 }
253 inline void SwCache::DecreaseMax( const sal_uInt16 nSub )
254 {
255     if ( nCurMax > nSub )
256         nCurMax = nCurMax - sal::static_int_cast< sal_uInt16 >(nSub);
257 #ifdef DBG_UTIL
258     ++nDecreaseMax;
259 #endif
260 }
261 
262 inline sal_Bool SwCacheObj::IsOwner( const void *pNew ) const
263 {
264     return pOwner && pOwner == pNew;
265 }
266 
267 inline SwCacheObj *SwCache::Next( SwCacheObj *pCacheObj)
268 {
269     if ( pCacheObj )
270         return pCacheObj->GetNext();
271     else
272         return NULL;
273 }
274 
275 inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn, sal_Bool bSeek ) :
276     rCache( rC ),
277     pObj( 0 ),
278     pOwner( pOwn )
279 {
280     if ( bSeek && pOwner && 0 != (pObj = rCache.Get( pOwner )) )
281         pObj->Lock();
282 }
283 
284 inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn,
285                               const sal_uInt16 nIndex ) :
286     rCache( rC ),
287     pObj( 0 ),
288     pOwner( pOwn )
289 {
290     if ( pOwner && 0 != (pObj = rCache.Get( pOwner, nIndex )) )
291         pObj->Lock();
292 }
293 
294 inline SwCacheObj *SwCacheAccess::Get()
295 {
296     if ( !pObj )
297         _Get();
298     return pObj;
299 }
300 
301 
302 #endif
303