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