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. 134 void ResetLRUOfst() { pFirst = pRealFirst; } 135 136 inline void IncreaseMax( const sal_uInt16 nAdd ); 137 inline void DecreaseMax( const sal_uInt16 nSub ); 138 sal_uInt16 GetCurMax() const { return nCurMax; } 139 inline SwCacheObj *First() { return pRealFirst; } 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: 149 SwSaveSetLRUOfst( SwCache &rC, const sal_uInt16 nOfst ) 150 : rCache( rC ) { rCache.SetLRUOfst( nOfst ); } 151 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 169 inline SwCacheObj *GetNext() { return pNext; } 170 inline SwCacheObj *GetPrev() { return pPrev; } 171 inline void SetNext( SwCacheObj *pNew ) { pNext = pNew; } 172 inline void SetPrev( SwCacheObj *pNew ) { pPrev = pNew; } 173 174 inline void SetCachePos( const sal_uInt16 nNew ) { nCachePos = nNew; } 175 176 protected: 177 const void *pOwner; 178 inline void SetOwner( const void *pNew ) { pOwner = pNew; } 179 180 public: 181 182 SwCacheObj( const void *pOwner ); 183 virtual ~SwCacheObj(); 184 185 inline const void *GetOwner() const { return pOwner; } 186 inline sal_Bool IsOwner( const void *pNew ) const; 187 188 inline sal_uInt16 GetCachePos() const { return nCachePos; } 189 inline void Invalidate() { pOwner = 0; } 190 191 inline sal_Bool IsLocked() const { return 0 != nLock; } 192 193 #ifndef DBG_UTIL 194 inline void Lock() { ++nLock; } 195 inline void Unlock() { --nLock; } 196 #else 197 void Lock(); 198 void Unlock(); 199 #endif 200 201 SwCacheObj *Next() { return pNext; } 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. 239 sal_Bool IsAvail() const { return pObj != 0; } 240 }; 241 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 } 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 258 inline sal_Bool SwCacheObj::IsOwner( const void *pNew ) const 259 { 260 return pOwner && pOwner == pNew; 261 } 262 263 inline SwCacheObj *SwCache::Next( SwCacheObj *pCacheObj) 264 { 265 if ( pCacheObj ) 266 return pCacheObj->GetNext(); 267 else 268 return NULL; 269 } 270 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 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 290 inline SwCacheObj *SwCacheAccess::Get() 291 { 292 if ( !pObj ) 293 _Get(); 294 return pObj; 295 } 296 297 298 #endif 299