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