LCOV - code coverage report
Current view: top level - sw/source/core/inc - swcache.hxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 43 44 97.7 %
Date: 2014-04-11 Functions: 23 23 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : #ifndef INCLUDED_SW_SOURCE_CORE_INC_SWCACHE_HXX
      20             : #define INCLUDED_SW_SOURCE_CORE_INC_SWCACHE_HXX
      21             : 
      22             : /*
      23             :  * Es werden Pointer auf Objekte verwaltet. Diese werden in einem einfachen
      24             :  * PtrArray verwaltet.
      25             :  * Angelegt (new) werden die Objekte von Cache-Zugriffsklassen, zuerstoert
      26             :  * werden die Objekte vom Cache.
      27             :  *
      28             :  * Auf die Objekte kann wahlweise per Index in das Array oder per Suche
      29             :  * zugegriffen werden. Soll per Index zugegriffen werden, so obliegt die
      30             :  * Verwaltung des Index dem Anwender des Cache.
      31             :  *
      32             :  * Fuer die verwalteten Cache-Objekte gibt es eine Basisklasse, von dieser
      33             :  * sind spezifische Klassen abzuleiten.
      34             :  * In der Basisklasse werden die Cache-Objekte eines Cache doppelt verkettet,
      35             :  * das ermoeglich die Implementierung eines LRU-Algorithmus.
      36             :  *
      37             :  * Der LRU kann in der Cache-Basisklasse manipuliert werden, indem ein
      38             :  * virtueller First-Pointer gesetzt wird. Dieser kann auf den echten ersten
      39             :  * plus einem Ofst gesetzt werden. Dadurch kann man den Anfangsbereich des
      40             :  * Cache sichern und so dafuer sorgen, dass man waehrend bestimmter
      41             :  * Operationen nicht den Cache versaut. Beispiel: Der Idle-Handler sollte nicht
      42             :  * den Cache fuer den sichtbaren Bereich vernichten.
      43             :  *
      44             :  * Der Cache kann in der Groesse erweitert und wieder verkleinert werden.
      45             :  * Beispiel: Fuer jede neue Shell wird der Cache fuer FormatInfo vergrossert
      46             :  * und beim Destruieren der Shell wieder verkleinert.
      47             :  *
      48             :  */
      49             : 
      50             : #include <vector>
      51             : 
      52             : #include <rtl/ustring.hxx>
      53             : 
      54             : class SwCacheObj;
      55             : 
      56             : typedef std::vector<SwCacheObj*> SwCacheObjArr;
      57             : class SwCache
      58             : {
      59             :     SwCacheObjArr m_aCacheObjects;
      60             :     std::vector<sal_uInt16> aFreePositions; //Freie Positionen fuer das Insert wenn
      61             :                                     //die Maximalgrenze nicht erreicht ist.
      62             :                                     //Immer wenn ein Objekt ausgetragen wird,
      63             :                                     //so wird seine Position hier eingetragen.
      64             : 
      65             :     SwCacheObj *pRealFirst;         //_immer_ der echte LRU-erste
      66             :     SwCacheObj *pFirst;             //der virtuelle erste.
      67             :     SwCacheObj *pLast;
      68             : 
      69             :           sal_uInt16 nCurMax;           //Mehr werden nicht aufgenommen.
      70             : 
      71             :     void DeleteObj( SwCacheObj *pObj );
      72             : 
      73             : #ifdef DBG_UTIL
      74             :     OString m_aName;
      75             :     long m_nAppend;           /// number of entries appended
      76             :     long m_nInsertFree;       /// number of entries inserted on freed position
      77             :     long m_nReplace;          /// number of LRU replacements
      78             :     long m_nGetSuccess;
      79             :     long m_nGetFail;
      80             :     long m_nToTop;            /// number of reordering (LRU)
      81             :     long m_nDelete;           /// number of explicit deletes
      82             :     long m_nGetSeek;          /// number of gets without index
      83             :     long m_nAverageSeekCnt;   /// number of seeks for all gets without index
      84             :     long m_nFlushCnt;         /// number of flush calls
      85             :     long m_nFlushedObjects;
      86             :     long m_nIncreaseMax;      /// number of cache size increases
      87             :     long m_nDecreaseMax;      /// number of cache size decreases
      88             : 
      89             :     void Check();
      90             : #endif
      91             : 
      92             : public:
      93             : 
      94             :     //nur sal_uInt8 hineinstecken!!!
      95             : #ifdef DBG_UTIL
      96             :     SwCache( const sal_uInt16 nInitSize, const OString &rNm );
      97             : #else
      98             :     SwCache( const sal_uInt16 nInitSize );
      99             : #endif
     100             :     // the destructor will free all objects still in the vector
     101             :     ~SwCache();
     102             : 
     103             :     void Flush( const sal_uInt8 nPercent = 100 );
     104             : 
     105             :     //bToTop == sal_False -> Keine LRU-Umsortierung!
     106             :     SwCacheObj *Get( const void *pOwner, const sal_Bool bToTop = sal_True );
     107             :     SwCacheObj *Get( const void *pOwner, const sal_uInt16 nIndex,
     108             :                      const sal_Bool bToTop = sal_True );
     109             :     void ToTop( SwCacheObj *pObj );
     110             : 
     111             :     sal_Bool Insert( SwCacheObj *pNew );
     112             :     void Delete( const void *pOwner );
     113             : //  void Delete( const void *pOwner, const sal_uInt16 nIndex );
     114             : 
     115             :     void SetLRUOfst( const sal_uInt16 nOfst );      //nOfst sagt wieviele unangetastet
     116             :                                                 //bleiben sollen.
     117        2683 :     void ResetLRUOfst() { pFirst = pRealFirst; }
     118             : 
     119             :     inline void IncreaseMax( const sal_uInt16 nAdd );
     120             :     inline void DecreaseMax( const sal_uInt16 nSub );
     121        6186 :     sal_uInt16 GetCurMax() const { return nCurMax; }
     122      106198 :     inline SwCacheObj *First() { return pRealFirst; }
     123             :     inline SwCacheObj *Last()  { return pLast; }
     124             :     inline SwCacheObj *Next( SwCacheObj *pCacheObj);
     125             :     inline SwCacheObj* operator[](sal_uInt16 nIndex) { return m_aCacheObjects[nIndex]; }
     126             :     inline sal_uInt16 size() { return m_aCacheObjects.size(); }
     127             : };
     128             : 
     129             : //Cache-Manipulation auf die sichere Art.
     130             : class SwSaveSetLRUOfst
     131             : {
     132             :     SwCache &rCache;
     133             : public:
     134        2683 :     SwSaveSetLRUOfst( SwCache &rC, const sal_uInt16 nOfst )
     135        2683 :         : rCache( rC )          { rCache.SetLRUOfst( nOfst );  }
     136             : 
     137        2683 :     ~SwSaveSetLRUOfst()         { rCache.ResetLRUOfst(); }
     138             : };
     139             : 
     140             : //Das allgemeine CacheObjekt. Anwender des Cache muessen eine Klasse vom
     141             : //CacheObjekt ableiten und dort die Nutzdaten unterbringen.
     142             : 
     143             : class SwCacheObj
     144             : {
     145             :     friend class SwCache;   //Der darf alles
     146             : 
     147             :     SwCacheObj *pNext;      //Fuer die LRU-Verkettung.
     148             :     SwCacheObj *pPrev;
     149             : 
     150             :     sal_uInt16 nCachePos;       //Position im Cache-Array.
     151             : 
     152             :     sal_uInt8       nLock;
     153             : 
     154     3454627 :     inline SwCacheObj *GetNext() { return pNext; }
     155      915987 :     inline SwCacheObj *GetPrev() { return pPrev; }
     156      624958 :     inline void SetNext( SwCacheObj *pNew )  { pNext = pNew; }
     157      793944 :     inline void SetPrev( SwCacheObj *pNew )  { pPrev = pNew; }
     158             : 
     159       83066 :     inline void   SetCachePos( const sal_uInt16 nNew ) { nCachePos = nNew; }
     160             : 
     161             : protected:
     162             :     const void *pOwner;
     163             :     inline void SetOwner( const void *pNew ) { pOwner = pNew; }
     164             : 
     165             : public:
     166             : 
     167             :     SwCacheObj( const void *pOwner );
     168             :     virtual ~SwCacheObj();
     169             : 
     170      184778 :     inline const void *GetOwner() const { return pOwner; }
     171             :     inline sal_Bool IsOwner( const void *pNew ) const;
     172             : 
     173      230553 :     inline sal_uInt16 GetCachePos() const { return nCachePos; }
     174             :     inline void Invalidate()          { pOwner = 0; }
     175             : 
     176       83008 :     inline sal_Bool IsLocked() const { return 0 != nLock; }
     177             : 
     178             : #ifdef DBG_UTIL
     179             :     void Lock();
     180             :     void Unlock();
     181             : #else
     182     1592389 :     inline void Lock() { ++nLock; }
     183     1592354 :     inline void Unlock() { --nLock; }
     184             : #endif
     185             : 
     186             :     SwCacheObj *Next() { return pNext; }
     187             :     SwCacheObj *Prev() { return pPrev; }
     188             : 
     189             : };
     190             : 
     191             : //Zugriffsklasse fuer den Cache. Im CTor wird das CacheObjekt erzeugt.
     192             : //Wenn der Cache keines herausrueckt wird der Member zunaechst auf 0 gesetzt.
     193             : //Beim Get wird dann eines erzeugt und, falls moeglich, in den Cache
     194             : //eingetragen.
     195             : //Anwender der des Cache muessen eine Klasse vom Access ableiten um
     196             : //fuer Typsicherheit zu sorgen, die Basisklasse sollte fuer das Get aber immer
     197             : //gerufen werden, ein Abgeleitetes Get sollte nur der Typsicherheit dienen.
     198             : //Cache-Objekte werden stets gelockt solange die Instanz lebt.
     199             : 
     200             : class SwCacheAccess
     201             : {
     202             :     SwCache &rCache;
     203             : 
     204             :     void _Get();
     205             : 
     206             : protected:
     207             :     SwCacheObj *pObj;
     208             :     const void *pOwner;     //Kann ggf. in NewObj benutzt werden.
     209             : 
     210             :     virtual SwCacheObj *NewObj() = 0;
     211             : 
     212             :     inline SwCacheObj *Get();
     213             : 
     214             :     inline SwCacheAccess( SwCache &rCache, const void *pOwner, sal_Bool bSeek = sal_True );
     215             :     inline SwCacheAccess( SwCache &rCache, const void *pOwner, const sal_uInt16 nIndex );
     216             : 
     217             : public:
     218             :     virtual ~SwCacheAccess();
     219             : 
     220             :     virtual bool IsAvailable() const;
     221             : 
     222             :     //Abkuerzung fuer diejenigen, die wissen, das die Ableitung das IsAvailable
     223             :     //nicht ueberladen haben.
     224      734585 :     bool IsAvail() const { return pObj != 0; }
     225             : };
     226             : 
     227        1752 : inline void SwCache::IncreaseMax( const sal_uInt16 nAdd )
     228             : {
     229        1752 :     nCurMax = nCurMax + sal::static_int_cast< sal_uInt16 >(nAdd);
     230             : #ifdef DBG_UTIL
     231             :     ++m_nIncreaseMax;
     232             : #endif
     233        1752 : }
     234        1751 : inline void SwCache::DecreaseMax( const sal_uInt16 nSub )
     235             : {
     236        1751 :     if ( nCurMax > nSub )
     237        1751 :         nCurMax = nCurMax - sal::static_int_cast< sal_uInt16 >(nSub);
     238             : #ifdef DBG_UTIL
     239             :     ++m_nDecreaseMax;
     240             : #endif
     241        1751 : }
     242             : 
     243     3337357 : inline sal_Bool SwCacheObj::IsOwner( const void *pNew ) const
     244             : {
     245     3337357 :     return pOwner && pOwner == pNew;
     246             : }
     247             : 
     248      105043 : inline SwCacheObj *SwCache::Next( SwCacheObj *pCacheObj)
     249             : {
     250      105043 :     if ( pCacheObj )
     251      105043 :         return pCacheObj->GetNext();
     252             :     else
     253           0 :         return NULL;
     254             : }
     255             : 
     256      420608 : inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn, sal_Bool bSeek ) :
     257             :     rCache( rC ),
     258             :     pObj( 0 ),
     259      420608 :     pOwner( pOwn )
     260             : {
     261      420608 :     if ( bSeek && pOwner && 0 != (pObj = rCache.Get( pOwner )) )
     262      358701 :         pObj->Lock();
     263      420608 : }
     264             : 
     265      799688 : inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn,
     266             :                               const sal_uInt16 nIndex ) :
     267             :     rCache( rC ),
     268             :     pObj( 0 ),
     269      799688 :     pOwner( pOwn )
     270             : {
     271      799688 :     if ( pOwner && 0 != (pObj = rCache.Get( pOwner, nIndex )) )
     272      686643 :         pObj->Lock();
     273      799688 : }
     274             : 
     275     1564096 : inline SwCacheObj *SwCacheAccess::Get()
     276             : {
     277     1564096 :     if ( !pObj )
     278       81847 :         _Get();
     279     1564096 :     return pObj;
     280             : }
     281             : 
     282             : #endif
     283             : 
     284             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10