1 /************************************************************************/
4 /************************************************************************/
5 #ifndef __MRU_CACHE_H_256FCF72_8663_41DC_B98A_B822F6007912__
6 #define __MRU_CACHE_H_256FCF72_8663_41DC_B98A_B822F6007912__
11 ////////////////////////////////////////////////////////////////////////////////////////////////////
13 // XyAtlMap: a moded CAtlMap
15 template< typename K
, typename V
, class KTraits
= CElementTraits
< K
>, class VTraits
= CElementTraits
< V
> >
19 typedef typename
KTraits::INARGTYPE KINARGTYPE
;
20 typedef typename
KTraits::OUTARGTYPE KOUTARGTYPE
;
21 typedef typename
VTraits::INARGTYPE VINARGTYPE
;
22 typedef typename
VTraits::OUTARGTYPE VOUTARGTYPE
;
28 CPair(/* _In_ */ KINARGTYPE key
) :
44 /* _In_ */ KINARGTYPE key
,
52 UINT
GetHash() const throw()
65 _In_
float fOptimalLoad
= 0.75f
,
66 _In_
float fLoThreshold
= 0.25f
,
67 _In_
float fHiThreshold
= 2.25f
,
68 _In_ UINT nBlockSize
= 10) throw();
70 size_t GetCount() const throw();
71 bool IsEmpty() const throw();
74 /* _In_ */ KINARGTYPE key
,
75 _Out_ VOUTARGTYPE value
) const;
76 const CPair
* Lookup(/* _In_ */ KINARGTYPE key
) const throw();
77 CPair
* Lookup(/* _In_ */ KINARGTYPE key
) throw();
78 V
& operator[](/* _In_ */ KINARGTYPE key
) throw(...);
80 POSITION
SetAtIfNotExists(
81 /* _In_ */ KINARGTYPE key
,
82 /* _In_ */ VINARGTYPE value
,
83 bool *new_item_added
);
86 /* _In_ */ KINARGTYPE key
,
87 /* _In_ */ VINARGTYPE value
);
90 /* _In_ */ VINARGTYPE value
);
92 bool RemoveKey(/* _In_ */ KINARGTYPE key
) throw();
94 void RemoveAtPos(_In_ POSITION pos
) throw();
96 POSITION
GetStartPosition() const throw();
98 _Inout_ POSITION
& pos
,
99 _Out_ KOUTARGTYPE key
,
100 _Out_ VOUTARGTYPE value
) const;
101 const CPair
* GetNext(_Inout_ POSITION
& pos
) const throw();
102 CPair
* GetNext(_Inout_ POSITION
& pos
) throw();
103 const K
& GetNextKey(_Inout_ POSITION
& pos
) const;
104 const V
& GetNextValue(_Inout_ POSITION
& pos
) const;
105 V
& GetNextValue(_Inout_ POSITION
& pos
);
108 _Out_ KOUTARGTYPE key
,
109 _Out_ VOUTARGTYPE value
) const;
110 CPair
* GetAt(_In_ POSITION pos
) throw();
111 const CPair
* GetAt(_In_ POSITION pos
) const throw();
112 const K
& GetKeyAt(_In_ POSITION pos
) const;
113 const V
& GetValueAt(_In_ POSITION pos
) const;
114 V
& GetValueAt(_In_ POSITION pos
);
116 UINT
GetHashTableSize() const throw();
119 _In_
bool bAllocNow
= true);
120 void EnableAutoRehash() throw();
121 void DisableAutoRehash() throw();
122 void Rehash(_In_ UINT nBins
= 0);
124 _In_
float fOptimalLoad
,
125 _In_
float fLoThreshold
,
126 _In_
float fHiThreshold
,
127 _In_
bool bRehashNow
= false);
130 void AssertValid() const;
138 float m_fOptimalLoad
;
139 float m_fLoThreshold
;
140 float m_fHiThreshold
;
141 size_t m_nHiRehashThreshold
;
142 size_t m_nLoRehashThreshold
;
149 bool IsLocked() const throw();
150 UINT
PickSize(_In_
size_t nElements
) const throw();
152 /* _In_ */ KINARGTYPE key
,
155 void FreeNode(_Inout_ CNode
* pNode
);
156 void FreePlexes() throw();
158 /* _In_ */ KINARGTYPE key
,
161 _Deref_out_opt_ CNode
*& pPrev
) const throw();
163 /* _In_ */ KINARGTYPE key
,
165 _In_ UINT nHash
) throw(...);
168 _In_opt_ CNode
* pPrev
) throw();
169 CNode
* FindNextNode(_In_ CNode
* pNode
) const throw();
170 void UpdateRehashThresholds() throw();
176 // Private to prevent use
177 XyAtlMap(_In_
const XyAtlMap
&) throw();
178 XyAtlMap
& operator=(_In_
const XyAtlMap
&) throw();
182 template< typename K
, typename V
, class KTraits
, class VTraits
>
183 inline size_t XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetCount() const throw()
185 return( m_nElements
);
188 template< typename K
, typename V
, class KTraits
, class VTraits
>
189 inline bool XyAtlMap
< K
, V
, KTraits
, VTraits
>::IsEmpty() const throw()
191 return( m_nElements
== 0 );
194 template< typename K
, typename V
, class KTraits
, class VTraits
>
195 inline V
& XyAtlMap
< K
, V
, KTraits
, VTraits
>::operator[](/* _In_ */ KINARGTYPE key
) throw(...)
202 pNode
= GetNode( key
, iBin
, nHash
, pPrev
);
205 pNode
= CreateNode( key
, iBin
, nHash
);
208 return( pNode
->m_value
);
211 template< typename K
, typename V
, class KTraits
, class VTraits
>
212 inline UINT XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetHashTableSize() const throw()
217 template< typename K
, typename V
, class KTraits
, class VTraits
>
218 inline void XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetAt(
220 _Out_ KOUTARGTYPE key
,
221 _Out_ VOUTARGTYPE value
) const
223 ATLENSURE( pos
!= NULL
);
225 CNode
* pNode
= static_cast< CNode
* >( pos
);
228 value
= pNode
->m_value
;
231 template< typename K
, typename V
, class KTraits
, class VTraits
>
232 inline typename XyAtlMap
< K
, V
, KTraits
, VTraits
>::CPair
* XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetAt(
233 _In_ POSITION pos
) throw()
235 ATLASSERT( pos
!= NULL
);
237 return( static_cast< CPair
* >( pos
) );
240 template< typename K
, typename V
, class KTraits
, class VTraits
>
241 inline const typename XyAtlMap
< K
, V
, KTraits
, VTraits
>::CPair
* XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetAt(
242 _In_ POSITION pos
) const throw()
244 ATLASSERT( pos
!= NULL
);
246 return( static_cast< const CPair
* >( pos
) );
249 template< typename K
, typename V
, class KTraits
, class VTraits
>
250 inline const K
& XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetKeyAt(_In_ POSITION pos
) const
252 ATLENSURE( pos
!= NULL
);
254 CNode
* pNode
= (CNode
*)pos
;
256 return( pNode
->m_key
);
259 template< typename K
, typename V
, class KTraits
, class VTraits
>
260 inline const V
& XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetValueAt(_In_ POSITION pos
) const
262 ATLENSURE( pos
!= NULL
);
264 CNode
* pNode
= (CNode
*)pos
;
266 return( pNode
->m_value
);
269 template< typename K
, typename V
, class KTraits
, class VTraits
>
270 inline V
& XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetValueAt(_In_ POSITION pos
)
272 ATLENSURE( pos
!= NULL
);
274 CNode
* pNode
= (CNode
*)pos
;
276 return( pNode
->m_value
);
279 template< typename K
, typename V
, class KTraits
, class VTraits
>
280 inline void XyAtlMap
< K
, V
, KTraits
, VTraits
>::DisableAutoRehash() throw()
285 template< typename K
, typename V
, class KTraits
, class VTraits
>
286 inline void XyAtlMap
< K
, V
, KTraits
, VTraits
>::EnableAutoRehash() throw()
288 ATLASSUME( m_nLockCount
> 0 );
292 template< typename K
, typename V
, class KTraits
, class VTraits
>
293 inline bool XyAtlMap
< K
, V
, KTraits
, VTraits
>::IsLocked() const throw()
295 return( m_nLockCount
!= 0 );
298 template< typename K
, typename V
, class KTraits
, class VTraits
>
299 UINT XyAtlMap
< K
, V
, KTraits
, VTraits
>::PickSize(_In_
size_t nElements
) const throw()
301 // List of primes such that s_anPrimes[i] is the smallest prime greater than 2^(5+i/3)
302 static const UINT s_anPrimes
[] =
304 17, 23, 29, 37, 41, 53, 67, 83, 103, 131, 163, 211, 257, 331, 409, 521, 647, 821,
305 1031, 1291, 1627, 2053, 2591, 3251, 4099, 5167, 6521, 8209, 10331,
306 13007, 16411, 20663, 26017, 32771, 41299, 52021, 65537, 82571, 104033,
307 131101, 165161, 208067, 262147, 330287, 416147, 524309, 660563,
308 832291, 1048583, 1321139, 1664543, 2097169, 2642257, 3329023, 4194319,
309 5284493, 6658049, 8388617, 10568993, 13316089, UINT_MAX
312 size_t nBins
= (size_t)(nElements
/m_fOptimalLoad
);
313 UINT nBinsEstimate
= UINT( UINT_MAX
< nBins
? UINT_MAX
: nBins
);
315 // Find the smallest prime greater than our estimate
317 while( nBinsEstimate
> s_anPrimes
[iPrime
] )
322 if( s_anPrimes
[iPrime
] == UINT_MAX
)
324 return( nBinsEstimate
);
328 return( s_anPrimes
[iPrime
] );
332 template< typename K
, typename V
, class KTraits
, class VTraits
>
333 typename XyAtlMap
< K
, V
, KTraits
, VTraits
>::CNode
* XyAtlMap
< K
, V
, KTraits
, VTraits
>::CreateNode(
334 /* _In_ */ KINARGTYPE key
,
336 _In_ UINT nHash
) throw(...)
340 if( m_ppBins
== NULL
)
344 bSuccess
= InitHashTable( m_nBins
);
347 AtlThrow( E_OUTOFMEMORY
);
351 pNode
= NewNode( key
, iBin
, nHash
);
356 template< typename K
, typename V
, class KTraits
, class VTraits
>
357 POSITION XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetStartPosition() const throw()
364 for( UINT iBin
= 0; iBin
< m_nBins
; iBin
++ )
366 if( m_ppBins
[iBin
] != NULL
)
368 return( POSITION( m_ppBins
[iBin
] ) );
376 template< typename K
, typename V
, class KTraits
, class VTraits
>
377 POSITION XyAtlMap
<K
, V
, KTraits
, VTraits
>::SetAtIfNotExists( /* _In_ */ KINARGTYPE key
, /* _In_ */ VINARGTYPE value
,
378 bool *new_item_added
)
387 *new_item_added
= false;
390 pNode
= GetNode( key
, iBin
, nHash
, pPrev
);
393 pNode
= CreateNode( key
, iBin
, nHash
);
396 pNode
->m_value
= value
;
400 RemoveAtPos( POSITION( pNode
) );
405 *new_item_added
= true;
409 return( POSITION( pNode
) );
412 template< typename K
, typename V
, class KTraits
, class VTraits
>
413 POSITION XyAtlMap
< K
, V
, KTraits
, VTraits
>::SetAt(
414 /* _In_ */ KINARGTYPE key
,
415 /* _In_ */ VINARGTYPE value
)
422 pNode
= GetNode( key
, iBin
, nHash
, pPrev
);
425 pNode
= CreateNode( key
, iBin
, nHash
);
428 pNode
->m_value
= value
;
432 RemoveAtPos( POSITION( pNode
) );
438 pNode
->m_value
= value
;
441 return( POSITION( pNode
) );
444 template< typename K
, typename V
, class KTraits
, class VTraits
>
445 void XyAtlMap
< K
, V
, KTraits
, VTraits
>::SetValueAt(
447 /* _In_ */ VINARGTYPE value
)
449 ATLASSUME( pos
!= NULL
);
451 CNode
* pNode
= static_cast< CNode
* >( pos
);
453 pNode
->m_value
= value
;
456 template< typename K
, typename V
, class KTraits
, class VTraits
>
457 XyAtlMap
< K
, V
, KTraits
, VTraits
>::XyAtlMap(
459 _In_
float fOptimalLoad
,
460 _In_
float fLoThreshold
,
461 _In_
float fHiThreshold
,
462 _In_ UINT nBlockSize
) throw() :
466 m_nLockCount( 0 ), // Start unlocked
467 m_fOptimalLoad( fOptimalLoad
),
468 m_fLoThreshold( fLoThreshold
),
469 m_fHiThreshold( fHiThreshold
),
470 m_nHiRehashThreshold( UINT_MAX
),
471 m_nLoRehashThreshold( 0 ),
474 m_nBlockSize( nBlockSize
)
476 ATLASSERT( nBins
> 0 );
477 ATLASSERT( nBlockSize
> 0 );
479 SetOptimalLoad( fOptimalLoad
, fLoThreshold
, fHiThreshold
, false );
482 template< typename K
, typename V
, class KTraits
, class VTraits
>
483 void XyAtlMap
< K
, V
, KTraits
, VTraits
>::SetOptimalLoad(
484 _In_
float fOptimalLoad
,
485 _In_
float fLoThreshold
,
486 _In_
float fHiThreshold
,
487 _In_
bool bRehashNow
)
489 ATLASSERT( fOptimalLoad
> 0 );
490 ATLASSERT( (fLoThreshold
>= 0) && (fLoThreshold
< fOptimalLoad
) );
491 ATLASSERT( fHiThreshold
> fOptimalLoad
);
493 m_fOptimalLoad
= fOptimalLoad
;
494 m_fLoThreshold
= fLoThreshold
;
495 m_fHiThreshold
= fHiThreshold
;
497 UpdateRehashThresholds();
499 if( bRehashNow
&& ((m_nElements
> m_nHiRehashThreshold
) ||
500 (m_nElements
< m_nLoRehashThreshold
)) )
502 Rehash( PickSize( m_nElements
) );
506 template< typename K
, typename V
, class KTraits
, class VTraits
>
507 void XyAtlMap
< K
, V
, KTraits
, VTraits
>::UpdateRehashThresholds() throw()
509 m_nHiRehashThreshold
= size_t( m_fHiThreshold
*m_nBins
);
510 m_nLoRehashThreshold
= size_t( m_fLoThreshold
*m_nBins
);
511 if( m_nLoRehashThreshold
< 17 )
513 m_nLoRehashThreshold
= 0;
517 template< typename K
, typename V
, class KTraits
, class VTraits
>
518 bool XyAtlMap
< K
, V
, KTraits
, VTraits
>::InitHashTable(_In_ UINT nBins
, _In_
bool bAllocNow
)
520 ATLASSUME( m_nElements
== 0 );
521 ATLASSERT( nBins
> 0 );
523 if( m_ppBins
!= NULL
)
531 ATLTRY( m_ppBins
= new CNode
*[nBins
] );
532 if( m_ppBins
== NULL
)
537 ATLENSURE( UINT_MAX
/ sizeof( CNode
* ) >= nBins
);
538 memset( m_ppBins
, 0, sizeof( CNode
* )*nBins
);
542 UpdateRehashThresholds();
547 template< typename K
, typename V
, class KTraits
, class VTraits
>
548 void XyAtlMap
< K
, V
, KTraits
, VTraits
>::RemoveAll()
551 if( m_ppBins
!= NULL
)
553 for( UINT iBin
= 0; iBin
< m_nBins
; iBin
++ )
557 pNext
= m_ppBins
[iBin
];
558 while( pNext
!= NULL
)
563 pNext
= pNext
->m_pNext
;
575 InitHashTable( PickSize( m_nElements
), false );
582 template< typename K
, typename V
, class KTraits
, class VTraits
>
583 XyAtlMap
< K
, V
, KTraits
, VTraits
>::~XyAtlMap() throw()
595 #pragma push_macro("new")
598 template< typename K
, typename V
, class KTraits
, class VTraits
>
599 typename XyAtlMap
< K
, V
, KTraits
, VTraits
>::CNode
* XyAtlMap
< K
, V
, KTraits
, VTraits
>::NewNode(
600 /* _In_ */ KINARGTYPE key
,
606 if( m_pFree
== NULL
)
611 pPlex
= CAtlPlex::Create( m_pBlocks
, m_nBlockSize
, sizeof( CNode
) );
614 AtlThrow( E_OUTOFMEMORY
);
616 pNode
= (CNode
*)pPlex
->data();
617 pNode
+= m_nBlockSize
-1;
618 for( int iBlock
= m_nBlockSize
-1; iBlock
>= 0; iBlock
-- )
620 pNode
->m_pNext
= m_pFree
;
625 ATLENSURE(m_pFree
!= NULL
);
627 m_pFree
= pNewNode
->m_pNext
;
631 ::new( pNewNode
) CNode( key
, nHash
);
635 pNewNode
->m_pNext
= m_pFree
;
642 pNewNode
->m_pNext
= m_ppBins
[iBin
];
643 m_ppBins
[iBin
] = pNewNode
;
645 if( (m_nElements
> m_nHiRehashThreshold
) && !IsLocked() )
647 Rehash( PickSize( m_nElements
) );
653 #pragma pop_macro("new")
655 template< typename K
, typename V
, class KTraits
, class VTraits
>
656 void XyAtlMap
< K
, V
, KTraits
, VTraits
>::FreeNode(_Inout_ CNode
* pNode
)
658 ATLENSURE( pNode
!= NULL
);
661 pNode
->m_pNext
= m_pFree
;
664 ATLASSUME( m_nElements
> 0 );
667 if( (m_nElements
< m_nLoRehashThreshold
) && !IsLocked() )
669 Rehash( PickSize( m_nElements
) );
672 if( m_nElements
== 0 )
678 template< typename K
, typename V
, class KTraits
, class VTraits
>
679 void XyAtlMap
< K
, V
, KTraits
, VTraits
>::FreePlexes() throw()
682 if( m_pBlocks
!= NULL
)
684 m_pBlocks
->FreeDataChain();
689 template< typename K
, typename V
, class KTraits
, class VTraits
>
690 typename XyAtlMap
< K
, V
, KTraits
, VTraits
>::CNode
* XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetNode(
691 /* _In_ */ KINARGTYPE key
,
694 _Deref_out_opt_ CNode
*& pPrev
) const throw()
698 nHash
= KTraits::Hash( key
);
699 iBin
= nHash
%m_nBins
;
701 if( m_ppBins
== NULL
)
708 for( CNode
* pNode
= m_ppBins
[iBin
]; pNode
!= NULL
; pNode
= pNode
->m_pNext
)
710 if( (pNode
->GetHash() == nHash
) && KTraits::CompareElements( pNode
->m_key
, key
) )
721 template< typename K
, typename V
, class KTraits
, class VTraits
>
722 bool XyAtlMap
< K
, V
, KTraits
, VTraits
>::Lookup(
723 /* _In_ */ KINARGTYPE key
,
724 _Out_ VOUTARGTYPE value
) const
731 pNode
= GetNode( key
, iBin
, nHash
, pPrev
);
737 value
= pNode
->m_value
;
742 template< typename K
, typename V
, class KTraits
, class VTraits
>
743 const typename XyAtlMap
< K
, V
, KTraits
, VTraits
>::CPair
* XyAtlMap
< K
, V
, KTraits
, VTraits
>::Lookup(
744 /* _In_ */ KINARGTYPE key
) const throw()
751 pNode
= GetNode( key
, iBin
, nHash
, pPrev
);
756 template< typename K
, typename V
, class KTraits
, class VTraits
>
757 typename XyAtlMap
< K
, V
, KTraits
, VTraits
>::CPair
* XyAtlMap
< K
, V
, KTraits
, VTraits
>::Lookup(
758 /* _In_ */ KINARGTYPE key
) throw()
765 pNode
= GetNode( key
, iBin
, nHash
, pPrev
);
770 template< typename K
, typename V
, class KTraits
, class VTraits
>
771 bool XyAtlMap
< K
, V
, KTraits
, VTraits
>::RemoveKey(/* _In_ */ KINARGTYPE key
) throw()
779 pNode
= GetNode( key
, iBin
, nHash
, pPrev
);
785 RemoveNode( pNode
, pPrev
);
790 template< typename K
, typename V
, class KTraits
, class VTraits
>
791 void XyAtlMap
< K
, V
, KTraits
, VTraits
>::RemoveNode(
793 _In_opt_ CNode
* pPrev
)
795 ATLENSURE( pNode
!= NULL
);
797 UINT iBin
= pNode
->GetHash() % m_nBins
;
801 ATLASSUME( m_ppBins
[iBin
] == pNode
);
802 m_ppBins
[iBin
] = pNode
->m_pNext
;
806 ATLASSERT( pPrev
->m_pNext
== pNode
);
807 pPrev
->m_pNext
= pNode
->m_pNext
;
812 template< typename K
, typename V
, class KTraits
, class VTraits
>
813 void XyAtlMap
< K
, V
, KTraits
, VTraits
>::RemoveAtPos(_In_ POSITION pos
)
815 ATLENSURE( pos
!= NULL
);
817 CNode
* pNode
= static_cast< CNode
* >( pos
);
819 UINT iBin
= pNode
->GetHash() % m_nBins
;
821 ATLASSUME( m_ppBins
[iBin
] != NULL
);
822 if( pNode
== m_ppBins
[iBin
] )
828 pPrev
= m_ppBins
[iBin
];
829 while( pPrev
->m_pNext
!= pNode
)
831 pPrev
= pPrev
->m_pNext
;
832 ATLASSERT( pPrev
!= NULL
);
835 RemoveNode( pNode
, pPrev
);
838 template< typename K
, typename V
, class KTraits
, class VTraits
>
839 void XyAtlMap
< K
, V
, KTraits
, VTraits
>::Rehash(_In_ UINT nBins
)
841 CNode
** ppBins
= NULL
;
845 nBins
= PickSize( m_nElements
);
848 if( nBins
== m_nBins
)
853 ATLTRACE(atlTraceMap
, 2, _T("Rehash: %u bins\n"), nBins
);
855 if( m_ppBins
== NULL
)
857 // Just set the new number of bins
858 InitHashTable( nBins
, false );
862 ATLTRY(ppBins
= new CNode
*[nBins
]);
865 AtlThrow( E_OUTOFMEMORY
);
868 ATLENSURE( UINT_MAX
/ sizeof( CNode
* ) >= nBins
);
869 memset( ppBins
, 0, nBins
*sizeof( CNode
* ) );
871 // Nothing gets copied. We just rewire the old nodes
872 // into the new bins.
873 for( UINT iSrcBin
= 0; iSrcBin
< m_nBins
; iSrcBin
++ )
877 pNode
= m_ppBins
[iSrcBin
];
878 while( pNode
!= NULL
)
883 pNext
= pNode
->m_pNext
; // Save so we don't trash it
884 iDestBin
= pNode
->GetHash()%nBins
;
885 pNode
->m_pNext
= ppBins
[iDestBin
];
886 ppBins
[iDestBin
] = pNode
;
896 UpdateRehashThresholds();
899 template< typename K
, typename V
, class KTraits
, class VTraits
>
900 void XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetNextAssoc(
901 _Inout_ POSITION
& pos
,
902 _Out_ KOUTARGTYPE key
,
903 _Out_ VOUTARGTYPE value
) const
908 ATLASSUME( m_ppBins
!= NULL
);
909 ATLENSURE( pos
!= NULL
);
912 pNext
= FindNextNode( pNode
);
914 pos
= POSITION( pNext
);
916 value
= pNode
->m_value
;
919 template< typename K
, typename V
, class KTraits
, class VTraits
>
920 const typename XyAtlMap
< K
, V
, KTraits
, VTraits
>::CPair
* XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetNext(
921 _Inout_ POSITION
& pos
) const throw()
926 ATLASSUME( m_ppBins
!= NULL
);
927 ATLASSERT( pos
!= NULL
);
930 pNext
= FindNextNode( pNode
);
932 pos
= POSITION( pNext
);
937 template< typename K
, typename V
, class KTraits
, class VTraits
>
938 typename XyAtlMap
< K
, V
, KTraits
, VTraits
>::CPair
* XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetNext(
939 _Inout_ POSITION
& pos
) throw()
941 ATLASSUME( m_ppBins
!= NULL
);
942 ATLASSERT( pos
!= NULL
);
944 CNode
* pNode
= static_cast< CNode
* >( pos
);
945 CNode
* pNext
= FindNextNode( pNode
);
947 pos
= POSITION( pNext
);
952 template< typename K
, typename V
, class KTraits
, class VTraits
>
953 const K
& XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetNextKey(
954 _Inout_ POSITION
& pos
) const
959 ATLASSUME( m_ppBins
!= NULL
);
960 ATLENSURE( pos
!= NULL
);
963 pNext
= FindNextNode( pNode
);
965 pos
= POSITION( pNext
);
967 return( pNode
->m_key
);
970 template< typename K
, typename V
, class KTraits
, class VTraits
>
971 const V
& XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetNextValue(
972 _Inout_ POSITION
& pos
) const
977 ATLASSUME( m_ppBins
!= NULL
);
978 ATLENSURE( pos
!= NULL
);
981 pNext
= FindNextNode( pNode
);
983 pos
= POSITION( pNext
);
985 return( pNode
->m_value
);
988 template< typename K
, typename V
, class KTraits
, class VTraits
>
989 V
& XyAtlMap
< K
, V
, KTraits
, VTraits
>::GetNextValue(
990 _Inout_ POSITION
& pos
)
995 ATLASSUME( m_ppBins
!= NULL
);
996 ATLENSURE( pos
!= NULL
);
999 pNext
= FindNextNode( pNode
);
1001 pos
= POSITION( pNext
);
1003 return( pNode
->m_value
);
1006 template< typename K
, typename V
, class KTraits
, class VTraits
>
1007 typename XyAtlMap
< K
, V
, KTraits
, VTraits
>::CNode
* XyAtlMap
< K
, V
, KTraits
, VTraits
>::FindNextNode(
1008 _In_ CNode
* pNode
) const throw()
1018 if( pNode
->m_pNext
!= NULL
)
1020 pNext
= pNode
->m_pNext
;
1027 iBin
= (pNode
->GetHash()%m_nBins
)+1;
1028 while( (pNext
== NULL
) && (iBin
< m_nBins
) )
1030 if( m_ppBins
[iBin
] != NULL
)
1032 pNext
= m_ppBins
[iBin
];
1043 template< typename K
, typename V
, class KTraits
, class VTraits
>
1044 void XyAtlMap
< K
, V
, KTraits
, VTraits
>::AssertValid() const
1046 ATLASSUME( m_nBins
> 0 );
1047 // non-empty map should have hash table
1048 ATLASSERT( IsEmpty() || (m_ppBins
!= NULL
) );
1052 #pragma push_macro("new")
1055 ////////////////////////////////////////////////////////////////////////////////////////////////////
1060 class KTraits
= CElementTraits
< K
>
1065 XyMru(std::size_t max_item_num
):_max_item_num(max_item_num
){}
1067 inline POSITION
UpdateCache(POSITION pos
)
1069 _list
.MoveToHead(pos
);
1072 inline POSITION
UpdateCache(POSITION pos
, const V
& value
)
1074 _list
.GetAt(pos
).second
= value
;
1075 _list
.MoveToHead(pos
);
1078 inline POSITION
UpdateCache(const K
& key
, const V
& value
)
1081 POSITION pos_hash_value
= NULL
;
1082 bool new_item_added
= false;
1083 pos
= _hash
.SetAtIfNotExists(key
, (POSITION
)NULL
, &new_item_added
);
1086 pos_hash_value
= _list
.AddHead( ListItem(pos
, value
) );
1087 _hash
.SetValueAt(pos
, pos_hash_value
);
1091 pos_hash_value
= _hash
.GetValueAt(pos
);
1092 _list
.GetAt(pos_hash_value
).second
= value
;
1093 _list
.MoveToHead(pos_hash_value
);
1095 if(_list
.GetCount()>_max_item_num
)
1097 _hash
.RemoveAtPos(_list
.GetTail().first
);
1100 return pos_hash_value
;
1102 inline POSITION
AddHeadIfNotExists(const K
& key
, const V
& value
, bool *new_item_added
)
1105 POSITION pos_hash_value
= NULL
;
1106 bool new_hash_item_added
= false;
1107 pos
= _hash
.SetAtIfNotExists(key
, (POSITION
)NULL
, &new_hash_item_added
);
1108 if (new_hash_item_added
)
1110 pos_hash_value
= _list
.AddHead( ListItem(pos
, value
) );
1111 _hash
.SetValueAt(pos
, pos_hash_value
);
1114 *new_item_added
= true;
1119 pos_hash_value
= _hash
.GetValueAt(pos
);
1122 *new_item_added
= false;
1125 if(_list
.GetCount()>_max_item_num
)
1127 _hash
.RemoveAtPos(_list
.GetTail().first
);
1130 return pos_hash_value
;
1132 inline void RemoveAll()
1138 inline POSITION
Lookup(const K
& key
) const
1141 if( _hash
.Lookup(key
,pos
) )
1150 inline V
& GetAt(POSITION pos
)
1152 return _list
.GetAt(pos
).second
;
1154 inline const V
& GetAt(POSITION pos
) const
1156 return _list
.GetAt(pos
).second
;
1158 inline const K
& GetKeyAt(POSITION pos
) const
1160 return _hash
.GetKeyAt(_list
.GetAt(pos
).first
);
1162 inline std::size_t SetMaxItemNum( std::size_t max_item_num
)
1164 _max_item_num
= max_item_num
;
1165 while(_list
.GetCount()>_max_item_num
)
1167 _hash
.RemoveAtPos(_list
.GetTail().first
);
1170 return _max_item_num
;
1172 inline std::size_t GetMaxItemNum() const { return _max_item_num
; }
1173 inline std::size_t GetCurItemNum() const { return _list
.GetCount(); }
1175 typedef std::pair
<POSITION
,V
> ListItem
;
1176 CAtlList
<ListItem
> _list
;
1177 XyAtlMap
<K
,POSITION
,KTraits
> _hash
;
1179 std::size_t _max_item_num
;
1185 class KTraits
= CElementTraits
< K
>
1187 class EnhancedXyMru
:public XyMru
<K
,V
,KTraits
>
1190 EnhancedXyMru(std::size_t max_item_num
):XyMru(max_item_num
),_cache_hit(0),_query_count(0){}
1192 std::size_t SetMaxItemNum( std::size_t max_item_num
, bool clear_statistic_info
=false )
1194 if(clear_statistic_info
)
1199 return __super::SetMaxItemNum(max_item_num
);
1201 void RemoveAll(bool clear_statistic_info
=false)
1203 if(clear_statistic_info
)
1208 __super::RemoveAll();
1211 inline POSITION
Lookup(const K
& key
)
1214 POSITION pos
= __super::Lookup(key
);
1215 _cache_hit
+= (pos
!=NULL
);
1218 inline POSITION
AddHeadIfNotExists(const K
& key
, const V
& value
, bool *new_item_added
)
1222 POSITION pos
= __super::AddHeadIfNotExists(key
, value
, &tmp
);
1223 _cache_hit
+= (tmp
==false);
1225 *new_item_added
= tmp
;
1229 inline std::size_t GetCacheHitCount() const { return _cache_hit
; }
1230 inline std::size_t GetQueryCount() const { return _query_count
; }
1232 std::size_t _cache_hit
;
1233 std::size_t _query_count
;
1236 #endif // end of __MRU_CACHE_H_256FCF72_8663_41DC_B98A_B822F6007912__