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