xref: /aoo41x/main/sw/source/core/inc/swcache.hxx (revision cdf0e10c)
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