1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#ifndef _SWCACHE_HXX
#define _SWCACHE_HXX
/*
* Es werden Pointer auf Objekte verwaltet. Diese werden in einem einfachen
* PtrArray verwaltet.
* Angelegt (new) werden die Objekte von Cache-Zugriffsklassen, zuerstoert
* werden die Objekte vom Cache.
*
* Auf die Objekte kann wahlweise per Index in das Array oder per Suche
* zugegriffen werden. Soll per Index zugegriffen werden, so obliegt die
* Verwaltung des Index dem Anwender des Cache.
*
* Fuer die verwalteten Cache-Objekte gibt es eine Basisklasse, von dieser
* sind spezifische Klassen abzuleiten.
* In der Basisklasse werden die Cache-Objekte eines Cache doppelt verkettet,
* das ermoeglich die Implementierung eines LRU-Algorithmus.
*
* Der LRU kann in der Cache-Basisklasse manipuliert werden, indem ein
* virtueller First-Pointer gesetzt wird. Dieser kann auf den echten ersten
* plus einem Ofst gesetzt werden. Dadurch kann man den Anfangsbereich des
* Cache sichern und so dafuer sorgen, dass man waehrend bestimmter
* Operationen nicht den Cache versaut. Beispiel: Der Idle-Handler sollte nicht
* den Cache fuer den sichtbaren Bereich vernichten.
*
* Der Cache kann in der Groesse erweitert und wieder verkleinert werden.
* Beispiel: Fuer jede neue Shell wird der Cache fuer FormatInfo vergrossert
* und beim Destruieren der Shell wieder verkleinert.
*
*/
#include <vector>
#ifndef _SVSTDARR_HXX
#include <svl/svstdarr.hxx>
#endif
class SwCacheObj;
SV_DECL_PTRARR_DEL(SwCacheObjArr,SwCacheObj*,1,1)
class SwCache : public SwCacheObjArr
{
std::vector<sal_uInt16> aFreePositions; //Freie Positionen fuer das Insert wenn
//die Maximalgrenze nicht erreicht ist.
//Immer wenn ein Objekt ausgetragen wird,
//so wird seine Position hier eingetragen.
SwCacheObj *pRealFirst; //_immer_ der echte LRU-erste
SwCacheObj *pFirst; //der virtuelle erste.
SwCacheObj *pLast;
const sal_uInt16 nMax; //Mehr sollen nicht aufgenommen werden,
//der Cache kann aber dynamisch um jeweils
//nMax vergroessert werden.
sal_uInt16 nCurMax; //Mehr werden nicht aufgenommen.
void DeleteObj( SwCacheObj *pObj );
#ifdef DBG_UTIL
rtl::OString m_aName;
long m_nAppend; /// number of entries appended
long m_nInsertFree; /// number of entries inserted on freed position
long m_nReplace; /// number of LRU replacements
long m_nGetSuccess;
long m_nGetFail;
long m_nToTop; /// number of reordering (LRU)
long m_nDelete; /// number of explicit deletes
long m_nGetSeek; /// number of gets without index
long m_nAverageSeekCnt; /// number of seeks for all gets without index
long m_nFlushCnt; /// number of flush calls
long m_nFlushedObjects;
long m_nIncreaseMax; /// number of cache size increases
long m_nDecreaseMax; /// number of cache size decreases
void Check();
#endif
public:
//nur sal_uInt8 hineinstecken!!!
#ifdef DBG_UTIL
SwCache( const sal_uInt16 nInitSize, const sal_uInt16 nGrowSize,
const rtl::OString &rNm );
~SwCache();
#else
SwCache( const sal_uInt16 nInitSize, const sal_uInt16 nGrowSize );
#endif
void Flush( const sal_uInt8 nPercent = 100 );
//bToTop == sal_False -> Keine LRU-Umsortierung!
SwCacheObj *Get( const void *pOwner, const sal_Bool bToTop = sal_True );
SwCacheObj *Get( const void *pOwner, const sal_uInt16 nIndex,
const sal_Bool bToTop = sal_True );
void ToTop( SwCacheObj *pObj );
sal_Bool Insert( SwCacheObj *pNew );
void Delete( const void *pOwner );
// void Delete( const void *pOwner, const sal_uInt16 nIndex );
void SetLRUOfst( const sal_uInt16 nOfst ); //nOfst sagt wieviele unangetastet
//bleiben sollen.
void ResetLRUOfst() { pFirst = pRealFirst; }
inline void IncreaseMax( const sal_uInt16 nAdd );
inline void DecreaseMax( const sal_uInt16 nSub );
sal_uInt16 GetCurMax() const { return nCurMax; }
inline SwCacheObj *First() { return pRealFirst; }
inline SwCacheObj *Last() { return pLast; }
inline SwCacheObj *Next( SwCacheObj *pCacheObj);
};
//Cache-Manipulation auf die sichere Art.
class SwSaveSetLRUOfst
{
SwCache &rCache;
public:
SwSaveSetLRUOfst( SwCache &rC, const sal_uInt16 nOfst )
: rCache( rC ) { rCache.SetLRUOfst( nOfst ); }
~SwSaveSetLRUOfst() { rCache.ResetLRUOfst(); }
};
//Das allgemeine CacheObjekt. Anwender des Cache muessen eine Klasse vom
//CacheObjekt ableiten und dort die Nutzdaten unterbringen.
class SwCacheObj
{
friend class SwCache; //Der darf alles
SwCacheObj *pNext; //Fuer die LRU-Verkettung.
SwCacheObj *pPrev;
sal_uInt16 nCachePos; //Position im Cache-Array.
sal_uInt8 nLock;
inline SwCacheObj *GetNext() { return pNext; }
inline SwCacheObj *GetPrev() { return pPrev; }
inline void SetNext( SwCacheObj *pNew ) { pNext = pNew; }
inline void SetPrev( SwCacheObj *pNew ) { pPrev = pNew; }
inline void SetCachePos( const sal_uInt16 nNew ) { nCachePos = nNew; }
protected:
const void *pOwner;
inline void SetOwner( const void *pNew ) { pOwner = pNew; }
public:
SwCacheObj( const void *pOwner );
virtual ~SwCacheObj();
inline const void *GetOwner() const { return pOwner; }
inline sal_Bool IsOwner( const void *pNew ) const;
inline sal_uInt16 GetCachePos() const { return nCachePos; }
inline void Invalidate() { pOwner = 0; }
inline sal_Bool IsLocked() const { return 0 != nLock; }
#ifdef DBG_UTIL
void Lock();
void Unlock();
#else
inline void Lock() { ++nLock; }
inline void Unlock() { --nLock; }
#endif
SwCacheObj *Next() { return pNext; }
SwCacheObj *Prev() { return pPrev; }
};
//Zugriffsklasse fuer den Cache. Im CTor wird das CacheObjekt erzeugt.
//Wenn der Cache keines herausrueckt wird der Member zunaechst auf 0 gesetzt.
//Beim Get wird dann eines erzeugt und, falls moeglich, in den Cache
//eingetragen.
//Anwender der des Cache muessen eine Klasse vom Access ableiten um
//fuer Typsicherheit zu sorgen, die Basisklasse sollte fuer das Get aber immer
//gerufen werden, ein Abgeleitetes Get sollte nur der Typsicherheit dienen.
//Cache-Objekte werden stets gelockt solange die Instanz lebt.
class SwCacheAccess
{
SwCache &rCache;
void _Get();
protected:
SwCacheObj *pObj;
const void *pOwner; //Kann ggf. in NewObj benutzt werden.
virtual SwCacheObj *NewObj() = 0;
inline SwCacheObj *Get();
inline SwCacheAccess( SwCache &rCache, const void *pOwner, sal_Bool bSeek = sal_True );
inline SwCacheAccess( SwCache &rCache, const void *pOwner, const sal_uInt16 nIndex );
public:
virtual ~SwCacheAccess();
virtual sal_Bool IsAvailable() const;
//Abkuerzung fuer diejenigen, die wissen, das die Ableitung das IsAvailable
//nicht ueberladen haben.
sal_Bool IsAvail() const { return pObj != 0; }
};
inline void SwCache::IncreaseMax( const sal_uInt16 nAdd )
{
nCurMax = nCurMax + sal::static_int_cast< sal_uInt16 >(nAdd);
#ifdef DBG_UTIL
++m_nIncreaseMax;
#endif
}
inline void SwCache::DecreaseMax( const sal_uInt16 nSub )
{
if ( nCurMax > nSub )
nCurMax = nCurMax - sal::static_int_cast< sal_uInt16 >(nSub);
#ifdef DBG_UTIL
++m_nDecreaseMax;
#endif
}
inline sal_Bool SwCacheObj::IsOwner( const void *pNew ) const
{
return pOwner && pOwner == pNew;
}
inline SwCacheObj *SwCache::Next( SwCacheObj *pCacheObj)
{
if ( pCacheObj )
return pCacheObj->GetNext();
else
return NULL;
}
inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn, sal_Bool bSeek ) :
rCache( rC ),
pObj( 0 ),
pOwner( pOwn )
{
if ( bSeek && pOwner && 0 != (pObj = rCache.Get( pOwner )) )
pObj->Lock();
}
inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn,
const sal_uInt16 nIndex ) :
rCache( rC ),
pObj( 0 ),
pOwner( pOwn )
{
if ( pOwner && 0 != (pObj = rCache.Get( pOwner, nIndex )) )
pObj->Lock();
}
inline SwCacheObj *SwCacheAccess::Get()
{
if ( !pObj )
_Get();
return pObj;
}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|