| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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. |
| * |
| */ |
| |
| #ifdef DBG_UTIL |
| #ifndef _STRING_HXX //autogen |
| #include <tools/string.hxx> |
| #endif |
| #endif |
| |
| #ifndef _SVSTDARR_HXX |
| #define _SVSTDARR_USHORTS |
| #include <svl/svstdarr.hxx> |
| #endif |
| |
| class SwCacheObj; |
| |
| SV_DECL_PTRARR_DEL(SwCacheObjArr,SwCacheObj*,1,1) |
| |
| class SwCache : public SwCacheObjArr |
| { |
| SvUShorts 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 |
| ByteString aName; |
| long nAppend; //Anzahl der Eintragungen durch Erweiterung. |
| long nInsertFree; //Anzahl der Eintragungen auf freie Plaetze. |
| long nReplace; //Anzahl der Ersetzungen durch ein neues Objekt |
| long nGetSuccess; //Anzahl der Erfolgreichen Get's |
| long nGetFail; //Anzahl der nicht Erfolgreichen Get's |
| long nToTop; //Anzahl der Umsortierungen (LRU) |
| long nDelete; //Anzahl der Loeschungen (von Aussen) |
| long nGetSeek; //Anzahl der Get's ohne Index |
| long nAverageSeekCnt; //Anzahl der Seek's fuer alle Get's ohne Index |
| long nFlushCnt; //Anzahl von Flush-Aufrufen. |
| long nFlushedObjects; //Anzahl der wg. Flush vernichteten Objekte |
| long nIncreaseMax; //Anzahl Cache-Erweiterungen |
| long nDecreaseMax; //Anzahl Cache-Verkleinerungen |
| |
| void Check(); //Wird bei swcache.cxx mit DEBUG aktiv! |
| #endif |
| |
| public: |
| |
| //nur sal_uInt8 hineinstecken!!! |
| #ifdef DBG_UTIL |
| SwCache( const sal_uInt16 nInitSize, const sal_uInt16 nGrowSize, |
| const ByteString &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; } |
| |
| #ifndef DBG_UTIL |
| inline void Lock() { ++nLock; } |
| inline void Unlock() { --nLock; } |
| #else |
| void Lock(); |
| void Unlock(); |
| #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 |
| ++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 |
| ++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 |