一个HASH CACHE类

本文介绍了一个基于散列算法实现的缓存类IHashCache及其节点类IHashCacheNode。IHashCache采用散列算法存储对象,并利用LRU算法管理缓存,支持自定义散列函数及调整LRU链。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原作者是kaman, 我作了一点改进。
C++代码  收藏代码
  1. #ifndef _IHASHCACHE_H  
  2. #define _IHASHCACHE_H  
  3.   
  4. #include "icache.h"  
  5. #include "imutexlock.h"  
  6. #include "ierror.h"  
  7. #include "iexception.h"  
  8.   
  9. template <class IObject, class IKey>  
  10. class IHashCache;  
  11.   
  12. // A class derived from 'ICacheNode', it cooperates with 'IHashCache'.   
  13. // @Description:  
  14. //      'IHashCacheNode'是'IHashCache'的结点类型,继承了'ICacheNode'与'IHashCache'配对。  
  15. //  可以储存结点有效期和Hash,LRU链等信息。  
  16. // @MT-Safe:  
  17. //      Yes / Required.  
  18. // @Notes:  
  19. //      Equality operator and relation equality operator should be overloaded.  
  20. // @SeeAlso:  
  21. //      'IHashCache', 'ICacheNode'  
  22. template <  
  23. class IObject,   
  24. //The key type of this cache.  
  25. class IKey  
  26. >  
  27. class IHashCacheNode : public ICacheNode<IObject, IKey>  
  28. {  
  29. public:  
  30.     // Constructor.  
  31.     // @Parameters:  
  32.     //      %Object         The Object to be stored.  
  33.     //      %Key            The key assoicated the object.  
  34.     //      %nSize          The size of the object.  
  35.     //      %nTimeToLive    The time the object lives in the cache. -1 is permanence.  
  36.     IHashCacheNode (IObject Object, const IKey &Key, long nSize = 0, time_t nTimeToLive = -1);  
  37.   
  38.     // virtual destructor.  
  39.     virtual  ~IHashCacheNode();  
  40.   
  41.     // Make a new copy of the object in this cachenode and export it.  
  42.     virtual IObject GetObject();  
  43.   
  44.     // Return the key in this cachenode .  
  45.     const IKey &GetKey();  
  46.   
  47. private:  
  48.     // Do the initial work for IHashCache.  
  49.     void Init (const IKey &Key);      
  50.   
  51.     // Prevent the cachenode from implicit conversion.  
  52.     IHashCacheNode(const IHashCacheNode< IObject,IKey > &right) {};  
  53.   
  54.     // Prevent the cachenode from doing equality operation.  
  55.     IHashCacheNode< IObject,IKey > & operator=(const IHashCacheNode< IObject,IKey > &right) {};  
  56.   
  57. public:       
  58.     // The next cachenode in hash table.  
  59.     IHashCacheNode *m_pHashNextNode;  
  60.   
  61.     // The previous cachenode in hash table.  
  62.     IHashCacheNode *m_pHashPrevNode;  
  63.   
  64.     // The next cachenode in LRU list(access list).  
  65.     IHashCacheNode *m_pAccessListNextNode;  
  66.   
  67.     // The previous cachenode in LRU list(access list).  
  68.     IHashCacheNode *m_pAccessListPrevNode;  
  69.   
  70.     // The accessed time of this cachenode.  
  71.     // @Description:  
  72.     //      Increment whenever this cachenode was exported.  
  73.     //  When this value equals the adjust rate which user defined, the LRU   
  74.     //  list will be adjusted, and this value will be set to zero.  
  75.     int m_nHits;  
  76.   
  77.     // The context of the object which is stored.  
  78.     IObject m_Object;  
  79.   
  80.     // The key associated with this cachenode.  
  81.     IKey m_Key;  
  82.   
  83.     friend class IHashCache<IObject, IKey>;  
  84. };  
  85.   
  86. template <class IObject, class IKey>  
  87. IHashCacheNode<IObject,IKey>::IHashCacheNode (IObject Object, const IKey &Key, long nSize, time_t nTimeToLive):ICacheNode<IObject, IKey>(nSize,nTimeToLive)  
  88. {  
  89.     m_Object = Object;  
  90.     Init( Key );  
  91. }  
  92.   
  93.   
  94. template <class IObject, class IKey>  
  95. IHashCacheNode<IObject,IKey>::~IHashCacheNode()  
  96. {  
  97. }  
  98.   
  99. template <class IObject, class IKey>  
  100. void IHashCacheNode<IObject,IKey>::Init (const IKey &Key)  
  101. {  
  102.     m_Key = Key;  
  103.   
  104.     m_pHashNextNode = NULL;  
  105.     m_pHashPrevNode = NULL;  
  106.     m_pAccessListNextNode = NULL;  
  107.     m_pAccessListPrevNode = NULL;  
  108.   
  109.     m_nHits = 0;  
  110. }  
  111.   
  112. template <class IObject, class IKey>  
  113. const IKey &IHashCacheNode<IObject, IKey>::GetKey()  
  114. {  
  115.     return m_Key;  
  116. }  
  117.   
  118. template <class IObject, class IKey>  
  119. IObject IHashCacheNode<IObject, IKey>::GetObject()  
  120. {  
  121.     return m_Object;  
  122. }  
  123.   
  124.   
  125. #define IHashCacheNodeType IHashCacheNode<IObject, IKey>  
  126.   
  127. // 'IHashCache'类继承了'ICache'类,并实现了相应的存取和筛选算法。  
  128. // @Description:  
  129. //      对于Cache的存取,'IHashCache'采用了散列算法,根据用户所提供的散列函数  
  130. //  对新储存的结点进行散列。至于筛选算法,则采用最近最少使用LRU算法,存  
  131. //  入CACHE的结点组成一条LRU链,用者可以指定改变LRU结点顺序的结点调用次  
  132. //  数。每当CACHE装满或结点过期时,'IHashCache'就会从LRU链头开始删除,以  
  133. //  滕出空间放入新结点。 用户还可指定每次删除CACHE时一次性删除的结点数。  
  134. // @Usage:  
  135. //      Overide '.Hash()' function.  
  136. // @Notes:  
  137. //      Equality operator and relation equality operator should be overloaded.  
  138. // @MT-Safe:  
  139. //      Yes / Required.  
  140. // @SeeAlso:  
  141. //      'ICache', IHashCacheNode'  
  142. template <  
  143. class IObject,   
  144. //The key type of this cache.  
  145. class IKey  
  146. >  
  147. class IHashCache: public ICache<IObject, IKey>  
  148. {  
  149. public:  
  150.     // Default constructor.  
  151.     IHashCache();  
  152.   
  153.     // Constructor with configuring parameters.  
  154.     // @Parameters:  
  155.     //      %nMaxMem            The max memory (bytes) the cache can use.  
  156.     //      %nMaxCacheBlock     The number of blocks in the hash table.  
  157.     //      %nMaxCacheSize      The max number of nodes can be stored.  
  158.     //      %nNumToReap         The number of node being deleted every time   
  159.     //                          invoking '.Reap()'  
  160.     //      %nAjustRate         The time of hiting that will change LRU list.  
  161.     IHashCache( long nMaxMem, int nMaxCacheBlock, int nMaxCacheSize, int nNumToReap, int nAdjustRate );  
  162.   
  163.     // Destructor.  
  164.     virtual ~IHashCache();  
  165.   
  166.     // Reset IHashCache's parameters.  
  167.     virtual void Set(long nMaxMem, int nMaxCacheBlock, int nMaxCacheSize, int nNumToReap, int nAdjustRate );  
  168.   
  169.     // Store an object to the cache with the specified key.  
  170.     bool Store (IObject Object, const IKey &Key, long nUsedMem = 0, time_t nTimeToLive = -1);  
  171.   
  172.     // Fetch an object according to the key specified. ICache   
  173.     // will return a copy of the object.  
  174.     IObject Fetch (const IKey &Key);  
  175.   
  176.     // Added by Wooce  
  177.     IObject FetchAndCache(const IKey &Key);  
  178.   
  179.     // Delete an object from the cache according to the key specified.  
  180.     // @Description:  
  181.     //      If the key didn't exist, it wouldn't delete anything and return   
  182.     //  true. If the key matched the item in the cache, it would delete   
  183.     //  it from the cache and return true. Return false if something wrong   
  184.     //  happens.  
  185.     bool Delete (const IKey &Key);  
  186.   
  187.     // Pure abstract function.  
  188.     // The hash function that the derived class should overload for the   
  189.     // hash algorthim use.  
  190.     virtual unsigned Hash( const IKey &Key ) = 0;  
  191.   
  192.     // 对Cache中的内容进行遍历。  
  193.     void TraverseContainer();  
  194.   
  195.     // 对LRU链进行遍历。  
  196.     void TraverseXX();  
  197.   
  198.     // 回调函数,在运行TraverseContainer时对每个结点回调,可被继承类重载。  
  199.     virtual void OnTraverseContainer(IHashCacheNodeType *pNode) {};  
  200.   
  201.     // 回调函数,在运行TraverseXX时对每个结点回调,可被继承类重载。  
  202.     virtual void OnTraverseXX(IHashCacheNodeType *pNode) {};  
  203.   
  204.     // Get the count of objects stored in the cache.  
  205.     int GetObjectCount ();  
  206.   
  207. protected:  
  208.     //Added by Wooce  
  209.     //   If an object not exists in the cache, we can use this function to get the object from other place such as database,etc  
  210.     virtual void GetCacheObject( const IKey &Key,IObject& object )=0;  
  211.   
  212.     // 跟据指定的KEY在CACHE中找寻相应的结点。  
  213.     IHashCacheNodeType * SearchNode (const IKey &Key);  
  214.   
  215.     // 删除CACHE中结点。  
  216.     int Reap ();  
  217.   
  218.     // CACHE被装满时返回TRUE。  
  219.     bool IsFull ();  
  220.   
  221.     // 对HASH表中KEY对应的行进行锁定。  
  222.     void ReadLockNodeByKey (const IKey &Key);  
  223.   
  224.     void WriteLockNodeByKey (const IKey &Key);  
  225.   
  226.     int TryLockWhenCache(const IKey &Key);  
  227.   
  228.     // 对HASH表中KEY对应的行进行解锁。  
  229.     void UnLockNodeByKey (const IKey &Key);  
  230.   
  231.     // 把结点连到HASH表中。  
  232.     bool AddNodeToContainer (IHashCacheNodeType *pNode);  
  233.   
  234.     // 把结点从HASH表中移除。  
  235.     bool DelNodeFromContainer (IHashCacheNodeType *pNode);  
  236.   
  237.     // 把结点连入LRU链。  
  238.     bool AddNodeToXX (IHashCacheNodeType *pNode);  
  239.   
  240.     // 把结点从HASH表中移除。  
  241.     bool DelNodeFromXX (IHashCacheNodeType *pNode);  
  242.   
  243.     // 对整条LRU链进行封锁。  
  244.     void LockXX ();  
  245.   
  246.     // 对LRU链进行解锁。  
  247.     void UnLockXX ();  
  248.   
  249.     // 调整LRU链。  
  250.     bool AdjustNodeFromXX (IHashCacheNodeType *pNode);  
  251.   
  252.     // 结点过期时的处理函数。  
  253.     bool TimeOutHandler (IHashCacheNodeType *pNode);  
  254.   
  255.     // 把指定的结点链入IHashCache中.  
  256.     bool StoreNode (IHashCacheNodeType *pNode);  
  257.   
  258.     // 删除指定结点与IHashCache的链结。  
  259.     void DeleteNode( IHashCacheNodeType* pNode );  
  260.   
  261.     // 增加结点时的回调函数,在结点插入前调用。  
  262.     virtual void OnInsertNode (IHashCacheNodeType *pNode) {};  
  263.   
  264.     // 删除结点时的回调函数,在结点删除前调用。  
  265.     virtual void OnDeleteNode (IHashCacheNodeType *pNode) {};  
  266.   
  267.     // 提取结点时的回调函数,在找到结点且返回之前调用。  
  268.     virtual void OnFetchNode (ICacheNodeType *pNode) {};  
  269.   
  270.     // 增加结点时封锁整个Cache,目的是为了保持Cache中结点数和所用内存空间  
  271.     // 与实际存入的结点相符合,不会出现结点数虚增,即结点数已增加而结点还在  
  272.     // 等符插入。  
  273.     void LockStore();  
  274.   
  275.     // LockStore()的解锁操作。  
  276.     void UnLockStore();  
  277.   
  278. private:  
  279.     // Initialize IHashCache's parameters.  
  280.     void Init( long nMaxMem, int nMaxCacheBlock, int nMaxCacheSize, int nNumToReap, int nAdjustRate );  
  281.   
  282.     // 把'IHashCache'中占用的内存去除。  
  283.     void Destory();  
  284.   
  285. protected:  
  286.     // The maximum memory can be used in the cache.  
  287.     long    m_nMaxMem;  
  288.   
  289.     // The used memory used by the cachenode already in the cache.  
  290.     long    m_nUsedMem;  
  291.   
  292.     // The max cachenode count can be stored in the cache.  
  293.     int     m_nCacheSize;  
  294.   
  295.     // The cachenode count already stored in the cache.  
  296.     int     m_nCacheCount;  
  297.   
  298.     // Max blocks in hash  
  299.     int     m_nCacheBlocks;   
  300.   
  301.     // How many objects should be cleared in one reap action  
  302.     int     m_nNumToReap;  
  303.   
  304.     // Only move the object to the end of access list when it was   
  305.     //hit m_nAdjustRate times  
  306.     int     m_nAdjustRate;        
  307.   
  308.     // The head pointers pointed to the first element in each hash table row.  
  309.     IHashCacheNodeType**        m_apCacheHead;  
  310.   
  311.     // The tail pointers pointed to the last element in each hash table row.  
  312.     IHashCacheNodeType**        m_apCacheTail;  
  313.   
  314.     // The head pointer pointed to the first element of LRU list(access list).  
  315.     IHashCacheNodeType*     m_pAccessListHead;  
  316.   
  317.     // The tail pointer pointed to the last element of LRU list(access list).  
  318.     IHashCacheNodeType*     m_pAccessListTail;  
  319.   
  320.     // An array of locks used for locking a specified row in hash table.  
  321.     // It will be used at the time adjusting the hash table which is no need to   
  322.     // lock the whole cache.  
  323.     IRWLock*    m_LockHash;  
  324.   
  325.     // A lock which locks the whole cache when adjusting LRU list.  
  326.     ILock   m_LockAccessList;  
  327.   
  328.     // A lock used when invoking store function.  
  329.     ILock   m_LockStore;  
  330.   
  331. };  
  332.   
  333. template <class IObject, class IKey>  
  334. IHashCache<IObject, IKey>::IHashCache()  
  335. {  
  336.     m_nMaxMem = 0;  
  337.     m_nUsedMem = 0;  
  338.     m_nCacheSize = 0;  
  339.     m_nCacheCount = 0;  
  340.     m_nCacheBlocks = 0;  
  341.     m_nNumToReap = 0;  
  342.     m_nAdjustRate = 0;  
  343.   
  344.     m_apCacheHead = NULL;  
  345.     m_apCacheTail = NULL;  
  346.     m_pAccessListHead = NULL;  
  347.     m_pAccessListTail = NULL;  
  348.     m_LockHash = NULL;  
  349. }  
  350.   
  351. template <class IObject, class IKey>  
  352. IHashCache<IObject, IKey>::IHashCache( long nMaxMem, int nMaxCacheBlock, int nMaxCacheSize, int nNumToReap, int nAdjustRate )  
  353. {  
  354.     Init( nMaxMem, nMaxCacheBlock, nMaxCacheSize, nNumToReap, nAdjustRate );  
  355. }  
  356.   
  357. template <class IObject, class IKey>  
  358. IHashCache<IObject,IKey>::~IHashCache()  
  359. {  
  360.     Destory();  
  361. }  
  362.   
  363. template <class IObject, class IKey>  
  364. void IHashCache<IObject, IKey>::Init( long nMaxMem, int nMaxCacheBlock, int nMaxCacheSize, int nNumToReap, int nAdjustRate )  
  365. {  
  366.     try  
  367.     {  
  368.         m_apCacheHead = m_apCacheTail = NULL;  
  369.         m_LockHash = NULL;  
  370.         XNew( m_apCacheHead , IHashCacheNodeType* [ nMaxCacheBlock ] );  
  371.         XNew( m_apCacheTail , IHashCacheNodeType* [ nMaxCacheBlock ] );  
  372.   
  373.         m_LockHash = new IRWLock [ nMaxCacheBlock ];  
  374.         if ( m_LockHash == NULL )  
  375.             throw IException( MEMNOTENOUGH, "Not enough memory" );  
  376.     } catch (...)  
  377.     {  
  378.         if ( m_apCacheHead != NULL )  
  379.             delete[] m_apCacheHead;  
  380.         if ( m_apCacheTail != NULL )  
  381.             delete[] m_apCacheTail;  
  382.         if ( m_LockHash != NULL )  
  383.             delete[] m_LockHash;  
  384.         throw;  
  385.     }  
  386.     for ( int i=0; i<nMaxCacheBlock; i++ )  
  387.         m_apCacheHead[ i ] = m_apCacheTail[ i ] = NULL;  
  388.   
  389.     m_pAccessListHead = NULL;  
  390.     m_pAccessListTail = NULL;  
  391.   
  392.     m_nMaxMem = nMaxMem;  
  393.     m_nUsedMem = 0;  
  394.     m_nCacheSize = nMaxCacheSize;  
  395.     m_nCacheCount = 0;  
  396.     m_nCacheBlocks = nMaxCacheBlock;  
  397.     m_nNumToReap = nNumToReap;  
  398.     m_nAdjustRate = nAdjustRate;      
  399. }  
  400.   
  401. template <class IObject, class IKey>  
  402. void IHashCache<IObject, IKey>::Destory()  
  403. {  
  404.     IHashCacheNodeType *p, *p1;  
  405.     if ( m_apCacheHead != NULL )  
  406.     {  
  407.         for ( int i=0; i < m_nCacheBlocks ; i++ )  
  408.         {  
  409.             p = m_apCacheHead[i];  
  410.             while ( p != NULL )  
  411.             {  
  412.                 p1 = p->m_pHashNextNode;  
  413.                 delete p;  
  414.                 p = p1;  
  415.             }  
  416.         }  
  417.         delete m_apCacheHead;  
  418.     }  
  419.     if ( m_apCacheTail != NULL )  
  420.         delete m_apCacheTail;  
  421.     if ( m_LockHash != NULL )  
  422.         delete[] m_LockHash;  
  423. }  
  424.   
  425.   
  426. template <class IObject, class IKey>  
  427. void IHashCache<IObject, IKey>::Set(long nMaxMem, int nMaxCacheBlock, int nMaxCacheSize, int nNumToReap, int nAdjustRate )  
  428. {  
  429.     Destory();  
  430.     Init( nMaxMem, nMaxCacheBlock, nMaxCacheSize, nNumToReap, nAdjustRate );  
  431. }  
  432.   
  433. template <class IObject, class IKey>  
  434. bool IHashCache<IObject,IKey>::Store( IObject Object, const IKey& Key, long nUsedMem, time_t nTimeToLive )  
  435. {  
  436.     IHashCacheNodeType *pNode;  
  437.   
  438.     try  
  439.     {  
  440.         XNew( pNode , IHashCacheNodeType( Object, Key, nUsedMem, nTimeToLive ) );  
  441.     } catch ( IException& e )  
  442.     {  
  443.         g_Error.Out( L_ALARM, e.GetErrorInfo() );  
  444.     }  
  445.     return StoreNode( pNode );  
  446. }  
  447.   
  448. template <class IObject, class IKey>  
  449. IHashCacheNodeType * IHashCache<IObject, IKey>::SearchNode (const IKey &Key)  
  450. {  
  451.     int nPos = Hash( Key ) % m_nCacheBlocks;  
  452.   
  453.     IHashCacheNodeType* pNode = m_apCacheTail[ nPos ];  
  454.     while ( pNode != NULL )  
  455.     {  
  456.         if ( pNode->m_Key == Key )  
  457.             break;  
  458.         else  
  459.             pNode = pNode->m_pHashPrevNode;  
  460.     }  
  461.     if ( pNode == NULL )    //Object not in cache  
  462.         return NULL;  
  463.     return pNode;  
  464. };  
  465.   
  466. template <class IObject, class IKey>  
  467. int IHashCache<IObject, IKey>::Reap ()  
  468. {  
  469.     int nDeleted = 0;  
  470.     IDEBUG( g_Error.Out( L_DEBUG, "IHashCache: Begin to reap\n") );  
  471.     for ( int i=0; i < m_nNumToReap; i++ )  
  472.     {  
  473.         LockXX();  
  474.         if ( m_pAccessListHead == NULL )  
  475.         {  
  476.             UnLockXX(); //**  
  477.             break;  
  478.         }  
  479.         IKey Key = m_pAccessListHead->m_Key;  
  480.         UnLockXX();  
  481.         if ( Delete( Key ) )  
  482.             nDeleted++;  
  483.     }  
  484.     IDEBUG( g_Error.Out( L_DEBUG, "ICache: Finished reaping.\n" ) );  
  485.     return nDeleted;  
  486. }  
  487.   
  488. template <class IObject, class IKey>  
  489. bool IHashCache<IObject, IKey>::IsFull ()  
  490. {  
  491.     return m_nCacheCount == m_nCacheSize || m_nUsedMem >= m_nMaxMem;   
  492. };  
  493.   
  494. template <class IObject, class IKey>  
  495. void IHashCache<IObject, IKey>::ReadLockNodeByKey ( const IKey &Key )  
  496. {  
  497.     int nPos = Hash( Key ) % m_nCacheBlocks;  
  498.     m_LockHash[ nPos ].ReadLock();  
  499. };  
  500.   
  501. template <class IObject, class IKey>  
  502. void IHashCache<IObject, IKey>::WriteLockNodeByKey ( const IKey &Key )  
  503. {  
  504.     int nPos = Hash( Key ) % m_nCacheBlocks;  
  505.     m_LockHash[ nPos ].WriteLock();  
  506. };  
  507.   
  508. template <class IObject, class IKey>  
  509. void IHashCache<IObject, IKey>::UnLockNodeByKey( const IKey &Key )  
  510. {  
  511.     int nPos = Hash( Key ) % m_nCacheBlocks;  
  512.     m_LockHash[ nPos ].Release();  
  513. };  
  514.   
  515. template <class IObject, class IKey>  
  516. int IHashCache<IObject, IKey>::TryLockWhenCache ( const IKey &Key )  
  517. {  
  518.     int nPos = Hash( Key ) % m_nCacheBlocks;  
  519.     return m_LockHash[ nPos ].TryWriteLock();  
  520. };  
  521.   
  522. template <class IObject, class IKey>  
  523. bool IHashCache<IObject, IKey>::AddNodeToContainer (IHashCacheNodeType *pNode)  
  524. {  
  525.     IHashCacheNodeType *pHashNode = (IHashCacheNodeType *)pNode;  
  526.   
  527.     int nPos = Hash( pHashNode->m_Key )  % m_nCacheBlocks;  
  528.   
  529.     if ( m_apCacheHead[ nPos ] == NULL )  
  530.     {  
  531.         m_apCacheHead[ nPos ] = pHashNode;  
  532.         m_apCacheTail[ nPos ] = pHashNode;  
  533.     } else  
  534.     {  
  535.         IHashCacheNodeType* pTail = m_apCacheTail[ nPos ];  
  536.         pHashNode->m_pHashPrevNode = pTail;  
  537.         //item->m_pHashNextNode = NULL;  //ommited  
  538.         pTail->m_pHashNextNode = pHashNode;  
  539.         m_apCacheTail[ nPos ] = pHashNode;  
  540.     }  
  541.     return true;  
  542. };  
  543.   
  544. template <class IObject, class IKey>  
  545. bool IHashCache<IObject, IKey>::DelNodeFromContainer (IHashCacheNodeType *pNode)  
  546. {  
  547.     IHashCacheNodeType *pPrevNode = pNode->m_pHashPrevNode;  
  548.     IHashCacheNodeType *pNextNode = pNode->m_pHashNextNode;  
  549.   
  550.     int nPos = Hash( pNode->m_Key )  % m_nCacheBlocks;  
  551.   
  552.     if ( pPrevNode == NULL )  
  553.         m_apCacheHead[ nPos ] = pNextNode;  
  554.     else  
  555.         pPrevNode->m_pHashNextNode = pNextNode;  
  556.   
  557.     if ( pNextNode == NULL )  
  558.         m_apCacheTail[ nPos ] = pPrevNode;  
  559.     else  
  560.         pNextNode->m_pHashPrevNode = pPrevNode;  
  561.     IDEBUG( g_Error.Out( L_DEBUG, "IHashCache: delete node from container.\n") );  
  562.     return true;  
  563. };  
  564.   
  565. template <class IObject, class IKey>  
  566. bool IHashCache<IObject, IKey>::AddNodeToXX (IHashCacheNodeType *pNode)  
  567. {  
  568.     if ( m_pAccessListHead == NULL )  
  569.     {  
  570.         m_pAccessListHead = pNode;  
  571.         m_pAccessListTail = pNode;  
  572.     } else  
  573.     {  
  574.         pNode->m_pAccessListPrevNode = m_pAccessListTail;  
  575.         //item->m_pAccessListNextNode = NULL;    //ommited  
  576.         m_pAccessListTail->m_pAccessListNextNode = pNode;  
  577.         m_pAccessListTail = pNode;  
  578.     }  
  579.     return true;  
  580. };  
  581.   
  582. template <class IObject, class IKey>  
  583. bool IHashCache<IObject, IKey>::DelNodeFromXX (IHashCacheNodeType *pNode)  
  584. {     
  585.     IHashCacheNodeType* pPrevNode = pNode->m_pAccessListPrevNode;  
  586.     IHashCacheNodeType* pNextNode = pNode->m_pAccessListNextNode;  
  587.   
  588.     if ( pPrevNode == NULL )  
  589.         m_pAccessListHead = pNextNode;  
  590.     else  
  591.         pPrevNode->m_pAccessListNextNode = pNextNode;  
  592.   
  593.     if ( pNextNode == NULL )  
  594.         m_pAccessListTail = pPrevNode;  
  595.     else  
  596.         pNextNode->m_pAccessListPrevNode = pPrevNode;  
  597.     IDEBUG( g_Error.Out( L_DEBUG, "IHashCache: delete node from XX\n") );   
  598.     return true;  
  599. };  
  600.   
  601. template <class IObject, class IKey>  
  602. void IHashCache<IObject, IKey>::LockXX ()  
  603. {  
  604.     m_LockAccessList.Lock();  
  605. };  
  606.   
  607. template <class IObject, class IKey>  
  608. void IHashCache<IObject, IKey>::UnLockXX ()  
  609. {  
  610.     m_LockAccessList.ReleaseLock();  
  611. };  
  612.   
  613. template <class IObject, class IKey>  
  614. bool IHashCache<IObject, IKey>::AdjustNodeFromXX (IHashCacheNodeType *pNode)  
  615. {  
  616.     pNode->m_nHits++;  
  617.     //Change the LRU list?  
  618.     if ( (pNode->m_nHits % m_nAdjustRate) == 0 )  
  619.     {  
  620.         //Move this node to the end of the list  
  621.         LockXX();  
  622.         if ( m_pAccessListTail != pNode )  
  623.         {  
  624.             // Remove node  
  625.             IHashCacheNodeType* pPrevNode = pNode->m_pAccessListPrevNode;  
  626.             IHashCacheNodeType* pNextNode = pNode->m_pAccessListNextNode;  
  627.             if ( pPrevNode == NULL )  
  628.                 m_pAccessListHead = pNextNode;  
  629.             else  
  630.                 pPrevNode->m_pAccessListNextNode = pNextNode;  
  631.             pNextNode->m_pAccessListPrevNode = pPrevNode;  
  632.   
  633.             //Append to tail  
  634.             m_pAccessListTail->m_pAccessListNextNode = pNode;  
  635.             pNode->m_pAccessListNextNode = NULL;  
  636.             pNode->m_pAccessListPrevNode = m_pAccessListTail;  
  637.             m_pAccessListTail = pNode;  
  638.         }  
  639.         UnLockXX();  
  640.     }  
  641.     return true;  
  642. };  
  643.   
  644. template <class IObject, class IKey>  
  645. bool IHashCache<IObject, IKey>::TimeOutHandler (IHashCacheNodeType *pNode)  
  646. {  
  647.     time_t now=time(NULL);  
  648.     if ( pNode->m_nTimeOut!=-1 && pNode->m_nTimeOut<now ) //This object already timeouted, shouldn't be used  
  649.     {  
  650.         DeleteNode( pNode );  
  651.         IDEBUG( g_Error.Out( L_DEBUG, "ICache: Key Expired, it will be deleted.\n" ) );  
  652.         return true;  
  653.     }  
  654.     return false;  
  655. };  
  656.   
  657. template <class IObject, class IKey>  
  658. void IHashCache<IObject, IKey>::LockStore()  
  659. {  
  660.     m_LockStore.Lock();  
  661. };  
  662.   
  663. template <class IObject, class IKey>  
  664. void IHashCache<IObject, IKey>::UnLockStore()  
  665. {  
  666.     m_LockStore.ReleaseLock();  
  667. };  
  668.   
  669. template <class IObject, class IKey>  
  670. void IHashCache<IObject, IKey>::TraverseContainer()  
  671. {  
  672.     int i;  
  673.     IHashCacheNodeType *pNode;  
  674.     g_Error.Out( L_ALARM, "-----Content of Cache------\n" );  
  675.     for (i=0; i<m_nCacheBlocks; i++)  
  676.     {  
  677.         m_LockHash[i].WriteLock();  
  678.         pNode = m_apCacheHead[ i ];  
  679.         while ( pNode != NULL )  
  680.         {  
  681.             OnTraverseContainer( pNode );  
  682.             pNode = pNode->m_pHashNextNode;  
  683.         }  
  684.         m_LockHash[i].Release();  
  685.     }     
  686.     g_Error.Out( L_ALARM, "\nCache Count = %d , Max Cache Size = %d\n", m_nCacheCount, m_nCacheSize ) ;  
  687.     g_Error.Out( L_ALARM, "----------------------------\n" ) ;  
  688. }  
  689.   
  690. template <class IObject, class IKey>  
  691. void IHashCache<IObject, IKey>::TraverseXX()  
  692. {  
  693.     LockXX();  
  694.     g_Error.Out( L_ALARM, "---------LRU List-------------\n" ) ;  
  695.     IHashCacheNodeType *pNode = m_pAccessListHead;  
  696.     while ( pNode != NULL )  
  697.     {  
  698.         OnTraverseXX( pNode );  
  699.         pNode = pNode->m_pAccessListNextNode;  
  700.     }  
  701.     g_Error.Out( L_ALARM, "------------------------------\n" );  
  702.     UnLockXX();  
  703. }  
  704.   
  705. template <class IObject, class IKey>  
  706. IObject IHashCache<IObject,IKey>::Fetch (const IKey &Key)  
  707. {     
  708.     IObject ResObj;   
  709.     ReadLockNodeByKey( Key );     
  710.     IHashCacheNodeType *pNode = SearchNode( Key );    
  711.     if ( pNode == NULL )  
  712.     {  
  713.         UnLockNodeByKey( Key );       
  714.         return ResObj;  
  715.     }  
  716.     bool NodeTimeOut = TimeOutHandler( pNode );  
  717.     if ( NodeTimeOut )  
  718.     {  
  719.         UnLockNodeByKey( Key );  
  720.         return ResObj;  
  721.     }  
  722.     OnFetchNode( pNode );  
  723.     pNode->SetLastAccessTime( time(NULL) );  
  724.     AdjustNodeFromXX( pNode );  
  725.     ResObj = pNode->GetObject();  
  726.     IDEBUG( g_Error.Out( L_DEBUG, "ICache: Fetched the node from cache.\n" ) );  
  727.     UnLockNodeByKey( Key );  
  728.     return ResObj;  
  729. }  
  730.   
  731. template <class IObject, class IKey>  
  732. IObject IHashCache<IObject,IKey>::FetchAndCache(const IKey &Key)  
  733. {     
  734.     IObject ResObj;   
  735.     ReadLockNodeByKey( Key );    
  736.     IHashCacheNodeType *pNode = SearchNode( Key );    
  737.     if( pNode==NULL )  
  738.     {  
  739.         UnLockNodeByKey(Key);  
  740.         if( TryLockWhenCache(Key)!=0 )  
  741.         {  
  742.             ReadLockNodeByKey(Key);  
  743.             pNode = SearchNode(Key);  
  744.         }  
  745.     }  
  746.     if ( pNode==NULL )            //   Not Existed in the Cache  
  747.     {  
  748.         try  
  749.         {  
  750.             GetCacheObject(Key,ResObj);  
  751.         }   
  752.         catch (IException e )  
  753.         {  
  754.             UnLockNodeByKey( Key );  
  755.             throw;  
  756.         } catch ( ... )  
  757.         {  
  758.             UnLockNodeByKey( Key );  
  759.             throw;  
  760.         }  
  761.         XNew( pNode , IHashCacheNodeType( ResObj, Key, 0, -1 ) );  
  762.         LockStore();  
  763.         if ( IsFull() )  
  764.         {  
  765.             for ( int i=0; i < m_nNumToReap; i++ )  
  766.             {  
  767.                 LockXX();  
  768.                 if ( m_pAccessListHead == NULL )  
  769.                 {  
  770.                     UnLockXX(); //**  
  771.                     break;  
  772.                 }  
  773.                 IHashCacheNodeType *p = m_pAccessListHead;  
  774.                 OnDeleteNode( p );  
  775.                 m_nCacheCount--;  
  776.                 m_nUsedMem -= p->m_nSize;  
  777.                 DelNodeFromXX( p );  
  778.                 UnLockXX();  
  779.                 DelNodeFromContainer( p );  
  780.                 delete p;  
  781.             }  
  782.   
  783.             if ( IsFull( ) ) //it almost couldn't be full.  
  784.             {  
  785.                 //Can't complete the reap operation, can't cache any more object  
  786.                 UnLockStore();  
  787.                 UnLockNodeByKey(Key);  
  788.                 return ResObj;  
  789.             }  
  790.         }  
  791.         OnInsertNode( pNode );  
  792.         m_nCacheCount++;  
  793.         m_nUsedMem += pNode->GetSize();  
  794.         AddNodeToContainer( pNode );  
  795.         LockXX();  
  796.         AddNodeToXX( pNode );  
  797.         UnLockXX();  
  798.         //ResObj = pNode->GetObject();  
  799.         IDEBUG( g_Error.Out( L_DEBUG, "ICache: Store a new node to cache.\n" ) );  
  800.         UnLockStore();  
  801.     } else  
  802.     {  
  803.         OnFetchNode( pNode );  
  804.         pNode->SetLastAccessTime( time(NULL) );  
  805.         AdjustNodeFromXX( pNode );  
  806.         ResObj = pNode->GetObject();  
  807.         IDEBUG( g_Error.Out( L_DEBUG, "ICache: Fetched the node from cache.\n" ) );  
  808.     }  
  809.     UnLockNodeByKey( Key );  
  810.     return ResObj;  
  811. }  
  812.   
  813. template <class IObject, class IKey>  
  814. bool IHashCache<IObject,IKey>::Delete (const IKey &Key)  
  815. {  
  816.     WriteLockNodeByKey( Key );  
  817.     IHashCacheNodeType *pNode = SearchNode( Key );  
  818.     if ( pNode == NULL )  
  819.     {  
  820.         UnLockNodeByKey( Key );  
  821.         return false;  
  822.     }  
  823.     DeleteNode( pNode );  
  824.     IDEBUG( g_Error.Out( L_DEBUG, "ICache: Delete a node from cache.\n" ) );  
  825.     UnLockNodeByKey( Key );  
  826.     return true;  
  827. }  
  828.   
  829. template <class IObject, class IKey>  
  830. void IHashCache<IObject, IKey>::DeleteNode( IHashCacheNodeType* pNode )  
  831. {  
  832.     OnDeleteNode( pNode );        
  833.     m_nCacheCount--;  
  834.     m_nUsedMem -= pNode->m_nSize;  
  835.     LockXX();  
  836.     DelNodeFromXX( pNode );  
  837.     UnLockXX();  
  838.     DelNodeFromContainer( pNode );  
  839.     delete pNode;  
  840. }  
  841.   
  842.   
  843. template <class IObject, class IKey>  
  844. bool IHashCache<IObject,IKey>::StoreNode (IHashCacheNodeType *pNode)  
  845. {  
  846.     IObject ResObj;  
  847.     LockStore();  
  848.     if ( IsFull() )  
  849.     {  
  850.         if ( Reap()<=0 ) //Only when the objects to be free are all be freed by other thread.  
  851.             if ( IsFull( ) ) //if reap()<=0 , it almost couldn't be full.  
  852.             {  
  853.                 //Can't complete the reap operation, can't cache any more object  
  854.                 Delete( pNode->GetKey() );  
  855.                 UnLockStore();  
  856.                 return false;  
  857.             }  
  858.     }  
  859.     WriteLockNodeByKey( pNode->GetKey() );  
  860.     IHashCacheNodeType *pOldNode = SearchNode( pNode->GetKey() );  
  861.     if ( pOldNode != NULL )  
  862.         DeleteNode( pOldNode );  
  863.     OnInsertNode( pNode );  
  864.     m_nCacheCount++;  
  865.     m_nUsedMem += pNode->GetSize();  
  866.     AddNodeToContainer( pNode );  
  867.     LockXX();  
  868.     AddNodeToXX( pNode );  
  869.     UnLockXX();  
  870.     //ResObj = pNode->GetObject();  
  871.     IDEBUG( g_Error.Out( L_DEBUG, "ICache: Store a new node to cache.\n" ) );  
  872.     UnLockNodeByKey( pNode->GetKey() );  
  873.     UnLockStore();  
  874.     return true;  
  875. }  
  876.   
  877. template <class IObject, class IKey>  
  878. int IHashCache<IObject,IKey>::GetObjectCount ()  
  879. {  
  880.     return m_nCacheCount;  
  881. }  
  882.   
  883. #endif  
cache hash table是一种用于存储和查找数据的数据结构。它结合了哈希表和高速缓存的特点,既可以快速定位数据,又可以提高数据访问的效率。 在Verilog中,我们可以使用硬件描述语言来实现一个cache hash table。首先,我们需要定义一组存储数据的缓存位置,这些位置称为缓存行。每个缓存行可以存储一个或多个数据,以及相应的标签和有效位。 然后,我们需要设计一个哈希函数来将每个数据的地址映射到缓存行。该哈希函数可以使用不同的算法,例如除法散列或乘法散列,以确保数据在缓存中的分布均匀。 在访问数据时,我们可以使用给定的地址来计算出哈希值,并从缓存中找到对应的缓存行。如果找到了对应的缓存行,我们可以根据标签和有效位来检查数据是否存在。如果存在,我们可以从缓存行中读取数据。如果数据不存在,我们可以通过访问主存或其他存储设备来获取数据,并将其存储在对应的缓存行中。 缓存hash表的设计需要考虑多个因素,例如缓存大小、哈希函数的设计、替换策略等。不同的设计选择将直接影响到缓存hash表的性能和效率。 综上所述,cache hash table是一种用于存储和查找数据的数据结构,在Verilog中可以通过硬件描述语言来实现。它结合了哈希表和高速缓存的特点,可以提高数据访问的效率,并根据地址映射数据到缓存行中。cache hash table的设计需要考虑多个因素,以实现高性能和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值