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