LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/stoc/source/corereflection - lrucache.hxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 54 55 98.2 %
Date: 2013-07-09 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             : #include "sal/log.hxx"
      28             : 
      29             : #include <boost/unordered_map.hpp>
      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     2033152 :     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( const t_Key & 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( const t_Key & rKey, const t_Val & 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( const t_Key & 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        4025 : 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        4025 :     , _pBlock( 0 )
     100             : {
     101        4025 :     if (_nCachedElements > 0)
     102             :     {
     103        4025 :         _pBlock = new CacheEntry[_nCachedElements];
     104        4025 :         _pHead  = _pBlock;
     105        4025 :         _pTail  = _pBlock + _nCachedElements -1;
     106     1038450 :         for ( sal_Int32 nPos = _nCachedElements; nPos--; )
     107             :         {
     108     1030400 :             _pBlock[nPos].pPred = _pBlock + nPos -1;
     109     1030400 :             _pBlock[nPos].pSucc = _pBlock + nPos +1;
     110             :         }
     111             :     }
     112        4025 : }
     113             : //__________________________________________________________________________________________________
     114             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
     115        3917 : inline LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::~LRU_Cache()
     116             : {
     117        3917 :     delete [] _pBlock;
     118        3917 : }
     119             : //__________________________________________________________________________________________________
     120             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
     121      199171 : inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::toFront( CacheEntry * pEntry ) const
     122             : {
     123      199171 :     if (pEntry != _pHead)
     124             :     {
     125             :         // cut out element
     126      152016 :         if (pEntry == _pTail)
     127             :         {
     128       12396 :             _pTail = pEntry->pPred;
     129             :         }
     130             :         else
     131             :         {
     132      139620 :             pEntry->pSucc->pPred = pEntry->pPred;
     133      139620 :             pEntry->pPred->pSucc = pEntry->pSucc;
     134             :         }
     135             :         // push to front
     136      152016 :         _pHead->pPred = pEntry;
     137      152016 :         pEntry->pSucc = _pHead;
     138      152016 :         _pHead        = pEntry;
     139             :     }
     140      199171 : }
     141             : //__________________________________________________________________________________________________
     142             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
     143             : inline sal_Bool LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::hasValue( const t_Key & rKey ) const
     144             : {
     145             :     ::osl::MutexGuard aGuard( _aCacheMutex );
     146             :     const typename t_Key2Element::const_iterator iFind( _aKey2Element.find( rKey ) );
     147             :     return (iFind != _aKey2Element.end());
     148             : }
     149             : //__________________________________________________________________________________________________
     150             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
     151      199238 : inline t_Val LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::getValue( const t_Key & rKey ) const
     152             : {
     153      199238 :     ::osl::MutexGuard aGuard( _aCacheMutex );
     154      199238 :     const typename t_Key2Element::const_iterator iFind( _aKey2Element.find( rKey ) );
     155      199238 :     if (iFind != _aKey2Element.end())
     156             :     {
     157      186775 :         CacheEntry * pEntry = (*iFind).second;
     158      186775 :         toFront( pEntry );
     159             : #ifdef __CACHE_DIAGNOSE
     160             :         SAL_INFO("stoc.corerefl", "> retrieved element \"" );
     161             :         SAL_INFO("stoc.corerefl", "" << pEntry->aKey);
     162             :         SAL_INFO("stoc.corerefl", "\" from cache <" );
     163             : #endif
     164      186775 :         return pEntry->aVal;
     165             :     }
     166       12463 :     return t_Val();
     167             : }
     168             : //__________________________________________________________________________________________________
     169             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
     170       12456 : inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::setValue(
     171             :     const t_Key & rKey, const t_Val & rValue )
     172             : {
     173       12456 :     ::osl::MutexGuard aGuard( _aCacheMutex );
     174       12456 :     if (_nCachedElements > 0)
     175             :     {
     176       12396 :         const typename t_Key2Element::const_iterator iFind( _aKey2Element.find( rKey ) );
     177             : 
     178             :         CacheEntry * pEntry;
     179       12396 :         if (iFind == _aKey2Element.end())
     180             :         {
     181       12396 :             pEntry = _pTail; // erase last element
     182             : #ifdef __CACHE_DIAGNOSE
     183             :             if (pEntry->aKey.getLength())
     184             :             {
     185             :                 SAL_INFO("stoc.corerefl", "> kicking element \"" );
     186             :                 SAL_INFO("stoc.corerefl", "" << pEntry->aKey);
     187             :                 SAL_INFO("stoc.corerefl", "\" from cache <" );
     188             :             }
     189             : #endif
     190       12396 :             _aKey2Element.erase( pEntry->aKey );
     191       12396 :             _aKey2Element[ pEntry->aKey = rKey ] = pEntry;
     192             :         }
     193             :         else
     194             :         {
     195           0 :             pEntry = (*iFind).second;
     196             : #ifdef __CACHE_DIAGNOSE
     197             :             SAL_INFO("stoc.corerefl", "> replacing element \"" );
     198             :             SAL_INFO("stoc.corerefl", "" << pEntry->aKey);
     199             :             SAL_INFO("stoc.corerefl", "\" in cache <" );
     200             : #endif
     201             :         }
     202       12396 :         pEntry->aVal = rValue;
     203       12396 :         toFront( pEntry );
     204       12456 :     }
     205       12456 : }
     206             : //__________________________________________________________________________________________________
     207             : template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual >
     208        3959 : inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::clear()
     209             : {
     210        3959 :     ::osl::MutexGuard aGuard( _aCacheMutex );
     211        3959 :     _aKey2Element.clear();
     212     1021422 :     for ( sal_Int32 nPos = _nCachedElements; nPos--; )
     213             :     {
     214     1013504 :         _pBlock[nPos].aKey = t_Key();
     215     1013504 :         _pBlock[nPos].aVal = t_Val();
     216             :     }
     217        3959 :     _nCachedElements = 0;
     218             : #ifdef __CACHE_DIAGNOSE
     219             :     SAL_INFO("stoc.corerefl", "> cleared cache <" );
     220             : #endif
     221        3959 : }
     222             : 
     223             : //==================================================================================================
     224             : struct FctHashOUString : public ::std::unary_function< const OUString &, size_t >
     225             : {
     226      232828 :     size_t operator()( const OUString & rKey ) const
     227      232828 :         { return rKey.hashCode(); }
     228             : };
     229             : 
     230             : /** Template instance for OUString keys, Any values.<br>
     231             : */
     232             : typedef LRU_Cache< OUString, ::com::sun::star::uno::Any,
     233             :                    FctHashOUString, ::std::equal_to< OUString > >
     234             :     LRU_CacheAnyByOUString;
     235             : 
     236             : 
     237             : #endif
     238             : 
     239             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10