LCOV - code coverage report
Current view: top level - libreoffice/stoc/source/tdmanager - lrucache.hxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 52 53 98.1 %
Date: 2012-12-27 Functions: 9 9 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 _LRU_CACHE_HXX_
      20             : #define _LRU_CACHE_HXX_
      21             : 
      22             : // __CACHE_DIAGNOSE forces cache size to 4 and works only for OUString keys
      23             : //  #define __CACHE_DIAGNOSE 1
      24             : 
      25             : #include <osl/mutex.hxx>
      26             : #include "rtl/ustring.hxx"
      27             : 
      28             : #include <boost/unordered_map.hpp>
      29             : 
      30             : 
      31             : /** Implementation of a least recently used (lru) cache.
      32             :     <br>
      33             :     @author Daniel Boelzle
      34             : */
      35             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
      36             : class LRU_Cache
      37             : {
      38      144896 :     struct CacheEntry
      39             :     {
      40             :         t_Key               aKey;
      41             :         t_Val               aVal;
      42             :         CacheEntry *        pPred;
      43             :         CacheEntry *        pSucc;
      44             :     };
      45             :     typedef ::boost::unordered_map< t_Key, CacheEntry *, t_KeyHash, t_KeyEqual > t_Key2Element;
      46             : 
      47             :     mutable ::osl::Mutex        _aCacheMutex;
      48             :     sal_Int32                   _nCachedElements;
      49             :     t_Key2Element               _aKey2Element;
      50             : 
      51             :     CacheEntry *                _pBlock;
      52             :     mutable CacheEntry *        _pHead;
      53             :     mutable CacheEntry *        _pTail;
      54             :     inline void toFront( CacheEntry * pEntry ) const;
      55             : 
      56             : public:
      57             :     /** Constructor:
      58             :         <br>
      59             :         @param nCachedElements number of elements to be cached; default param set to 128
      60             :     */
      61             :     inline LRU_Cache( sal_Int32 nCachedElements = 128 );
      62             :     /** Destructor: releases all cached elements and keys.
      63             :         <br>
      64             :     */
      65             :     inline ~LRU_Cache();
      66             : 
      67             :     /** Retrieves a value from the cache. Returns default constructed value,
      68             :         if none was found.
      69             :         <br>
      70             :         @param rKey a key
      71             :         @return value
      72             :     */
      73             :     inline t_Val getValue( t_Key const & rKey ) const;
      74             :     /** Sets a value to be cached for given key.
      75             :         <br>
      76             :         @param rKey a key
      77             :         @param rValue a value
      78             :     */
      79             :     inline void setValue( t_Key const & rKey, t_Val const & rValue );
      80             :     /** Tests whether a value is cached for given key.
      81             :         <br>
      82             :         @param rKey a key
      83             :         @return true, if value is cached
      84             :     */
      85             :     inline sal_Bool hasValue( t_Key const & rKey ) const;
      86             :     /** Clears the cache, thus releasing all cached elements and keys.
      87             :         <br>
      88             :     */
      89             :     inline void clear();
      90             : };
      91             : //__________________________________________________________________________________________________
      92             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
      93         259 : inline LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::LRU_Cache( sal_Int32 nCachedElements )
      94             : #ifdef __CACHE_DIAGNOSE
      95             :     : _nCachedElements( 4 )
      96             : #else
      97             :     : _nCachedElements( nCachedElements )
      98             : #endif
      99         259 :     , _pBlock( 0 )
     100             : {
     101         259 :     if (_nCachedElements > 0)
     102             :     {
     103         259 :         _pBlock = new CacheEntry[_nCachedElements];
     104         259 :         _pHead  = _pBlock;
     105         259 :         _pTail  = _pBlock + _nCachedElements -1;
     106      133126 :         for ( sal_Int32 nPos = _nCachedElements; nPos--; )
     107             :         {
     108      132608 :             _pBlock[nPos].pPred = _pBlock + nPos -1;
     109      132608 :             _pBlock[nPos].pSucc = _pBlock + nPos +1;
     110             :         }
     111             :     }
     112         259 : }
     113             : //__________________________________________________________________________________________________
     114             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
     115          24 : inline LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::~LRU_Cache()
     116             : {
     117          24 :     delete [] _pBlock;
     118          24 : }
     119             : //__________________________________________________________________________________________________
     120             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
     121       17521 : inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::toFront(
     122             :     CacheEntry * pEntry ) const
     123             : {
     124       17521 :     if (pEntry != _pHead)
     125             :     {
     126             :         // cut out element
     127       15574 :         if (pEntry == _pTail)
     128             :         {
     129        6425 :             _pTail = pEntry->pPred;
     130             :         }
     131             :         else
     132             :         {
     133        9149 :             pEntry->pSucc->pPred = pEntry->pPred;
     134        9149 :             pEntry->pPred->pSucc = pEntry->pSucc;
     135             :         }
     136             :         // push to front
     137       15574 :         _pHead->pPred = pEntry;
     138       15574 :         pEntry->pSucc = _pHead;
     139       15574 :         _pHead        = pEntry;
     140             :     }
     141       17521 : }
     142             : //__________________________________________________________________________________________________
     143             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
     144             : inline sal_Bool LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::hasValue(
     145             :     t_Key const & rKey ) const
     146             : {
     147             :     ::osl::MutexGuard aGuard( _aCacheMutex );
     148             :     typename t_Key2Element::const_iterator const iFind( _aKey2Element.find( rKey ) );
     149             :     return (iFind != _aKey2Element.end());
     150             : }
     151             : //__________________________________________________________________________________________________
     152             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
     153       17522 : inline t_Val LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::getValue(
     154             :     t_Key const & rKey ) const
     155             : {
     156       17522 :     ::osl::MutexGuard aGuard( _aCacheMutex );
     157       17522 :     const typename t_Key2Element::const_iterator iFind( _aKey2Element.find( rKey ) );
     158       17522 :     if (iFind != _aKey2Element.end())
     159             :     {
     160       11096 :         CacheEntry * pEntry = (*iFind).second;
     161       11096 :         toFront( pEntry );
     162             : #ifdef __CACHE_DIAGNOSE
     163             :         OSL_TRACE( "> retrieved element \"" );
     164             :         OSL_TRACE( "%s", ::rtl::OUStringToOString( pEntry->aKey, RTL_TEXTENCODING_ASCII_US ).getStr() );
     165             :         OSL_TRACE( "\" from cache <" );
     166             : #endif
     167       11096 :         return pEntry->aVal;
     168             :     }
     169        6426 :     return t_Val();
     170             : }
     171             : //__________________________________________________________________________________________________
     172             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
     173        6425 : inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::setValue(
     174             :     t_Key const & rKey, t_Val const & rValue )
     175             : {
     176        6425 :     if (_nCachedElements > 0)
     177             :     {
     178        6425 :         ::osl::MutexGuard aGuard( _aCacheMutex );
     179        6425 :         typename t_Key2Element::const_iterator const iFind( _aKey2Element.find( rKey ) );
     180             : 
     181             :         CacheEntry * pEntry;
     182        6425 :         if (iFind == _aKey2Element.end())
     183             :         {
     184        6425 :             pEntry = _pTail; // erase last element
     185             : #ifdef __CACHE_DIAGNOSE
     186             :             if (pEntry->aKey.getLength())
     187             :             {
     188             :                 OSL_TRACE( "> kicking element \"" );
     189             :                 OSL_TRACE( "%s", ::rtl::OUStringToOString( pEntry->aKey, RTL_TEXTENCODING_ASCII_US ).getStr() );
     190             :                 OSL_TRACE( "\" from cache <" );
     191             :             }
     192             : #endif
     193        6425 :             _aKey2Element.erase( pEntry->aKey );
     194        6425 :             _aKey2Element[ pEntry->aKey = rKey ] = pEntry;
     195             :         }
     196             :         else
     197             :         {
     198           0 :             pEntry = (*iFind).second;
     199             : #ifdef __CACHE_DIAGNOSE
     200             :             OSL_TRACE( "> replacing element \"" );
     201             :             OSL_TRACE( "%s", ::rtl::OUStringToOString( pEntry->aKey, RTL_TEXTENCODING_ASCII_US ).getStr() );
     202             :             OSL_TRACE( "\" in cache <" );
     203             : #endif
     204             :         }
     205        6425 :         pEntry->aVal = rValue;
     206        6425 :         toFront( pEntry );
     207             :     }
     208        6425 : }
     209             : //__________________________________________________________________________________________________
     210             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
     211          39 : inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::clear()
     212             : {
     213          39 :     ::osl::MutexGuard aGuard( _aCacheMutex );
     214          39 :     _aKey2Element.clear();
     215       20046 :     for ( sal_Int32 nPos = _nCachedElements; nPos--; )
     216             :     {
     217       19968 :         _pBlock[nPos].aKey = t_Key();
     218       20007 :         _pBlock[nPos].aVal = t_Val();
     219             :     }
     220             : #ifdef __CACHE_DIAGNOSE
     221             :     OSL_TRACE( "> cleared cache <" );
     222             : #endif
     223          39 : }
     224             : 
     225             : //==================================================================================================
     226             : struct FctHashOUString : public ::std::unary_function< ::rtl::OUString const &, size_t >
     227             : {
     228       36692 :     size_t operator()( ::rtl::OUString const & rKey ) const
     229       36692 :         { return (size_t)rKey.hashCode(); }
     230             : };
     231             : 
     232             : /** Template instance for OUString keys, Any values.<br>
     233             : */
     234             : typedef LRU_Cache< ::rtl::OUString, ::com::sun::star::uno::Any,
     235             :                    FctHashOUString, ::std::equal_to< ::rtl::OUString > >
     236             :     LRU_CacheAnyByOUString;
     237             : 
     238             : 
     239             : #endif
     240             : 
     241             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10