-rw-r--r-- | shared-code/LRUCache.h | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/shared-code/LRUCache.h b/shared-code/LRUCache.h new file mode 100644 index 0000000..569e829 --- a/dev/null +++ b/shared-code/LRUCache.h | |||
@@ -0,0 +1,113 @@ | |||
1 | #ifndef__LRUCACHE_H | ||
2 | #define__LRUCACHE_H | ||
3 | |||
4 | namespace Klever { | ||
5 | |||
6 | template<class IDX,class ARGIDX,class DATA> | ||
7 | class CLRUCache : public CObject { | ||
8 | public: | ||
9 | struct CacheEntry{ | ||
10 | enum cacheState{ | ||
11 | cacheClean, cacheDirty, cacheEmpty | ||
12 | }; | ||
13 | cacheStatem_State; | ||
14 | UINT m_hits; | ||
15 | |||
16 | IDX m_idx; | ||
17 | DATA* m_pData; | ||
18 | |||
19 | CacheEntry() { m_State=cacheEmpty; VERIFY(m_pData=new DATA); m_hits=0; } | ||
20 | virtual ~CacheEntry() { delete m_pData; } | ||
21 | }; | ||
22 | typedef CMap<IDX,ARGIDX,CacheEntry*,CacheEntry*> CCacheMap; | ||
23 | typedef CList<CacheEntry*,CacheEntry*> CCacheList; | ||
24 | |||
25 | CCacheList m_Cache; | ||
26 | CCacheMap m_Map; | ||
27 | |||
28 | CLRUCache(UINT cacheSize){ | ||
29 | for(int tmp=0;tmp<cacheSize;tmp++){ | ||
30 | CacheEntry* p = new CacheEntry; | ||
31 | m_Cache.AddTail(p); | ||
32 | } | ||
33 | } | ||
34 | virtual ~CLRUCache(){ | ||
35 | Flush(); | ||
36 | POSITION p = m_Cache.GetHeadPosition(); | ||
37 | while(p){ | ||
38 | CacheEntry* c = m_Cache.GetNext(p); | ||
39 | delete c; | ||
40 | } | ||
41 | } | ||
42 | |||
43 | DATA* GetCached(ARGIDX idx,BOOL bLoad=TRUE) { | ||
44 | CacheEntry* rv; | ||
45 | if(m_Map.Lookup(idx,rv)){ | ||
46 | rv->m_hits++; | ||
47 | PopUp(rv); | ||
48 | return rv->m_pData; | ||
49 | } | ||
50 | if(!bLoad) | ||
51 | return NULL; | ||
52 | rv = m_Cache.GetTail(); | ||
53 | ASSERT(rv); | ||
54 | switch(rv->m_State){ | ||
55 | case CacheEntry::cacheDirty: | ||
56 | FlushEntry(rv); | ||
57 | case CacheEntry::cacheClean: | ||
58 | m_Map.RemoveKey(rv->m_idx); | ||
59 | rv->m_State=CacheEntry::cacheEmpty; | ||
60 | case CacheEntry::cacheEmpty: | ||
61 | break; | ||
62 | default: | ||
63 | ASSERT(FALSE); | ||
64 | } | ||
65 | if(!_ReadIn(idx,rv->m_pData)) | ||
66 | return NULL; | ||
67 | rv->m_hits=1; | ||
68 | rv->m_State=CacheEntry::cacheClean; | ||
69 | rv->m_idx=idx; | ||
70 | m_Map[idx]=rv; | ||
71 | PopUp(rv); | ||
72 | return rv->m_pData; | ||
73 | } | ||
74 | BOOL MakeDirty(ARGIDX idx) { | ||
75 | CacheEntry* pEntry; | ||
76 | if(m_Map.Lookup(idx,pEntry)){ | ||
77 | ASSERT(pEntry->m_State==CacheEntry::cacheClean || pEntry->m_State==CacheEntry::cacheDirty); | ||
78 | pEntry->m_State=CacheEntry::cacheDirty; | ||
79 | return TRUE; | ||
80 | } | ||
81 | return FALSE; | ||
82 | } | ||
83 | BOOL Flush() { | ||
84 | POSITION p = m_Cache.GetHeadPosition(); | ||
85 | while(p){ | ||
86 | CacheEntry* pEntry = m_Cache.GetNext(p); | ||
87 | ASSERT(pEntry); | ||
88 | FlushEntry(pEntry); | ||
89 | } | ||
90 | return TRUE; | ||
91 | } | ||
92 | BOOL FlushEntry(CacheEntry* pEntry) { | ||
93 | if(pEntry->m_State==CacheEntry::cacheDirty){ | ||
94 | BOOL rv = _WriteOut(pEntry->m_idx,pEntry->m_pData); | ||
95 | if(rv) | ||
96 | pEntry->m_State=CacheEntry::cacheClean; | ||
97 | } | ||
98 | return FALSE; | ||
99 | } | ||
100 | void PopUp(CacheEntry* pEntry) { | ||
101 | POSITION p = m_Cache.Find(pEntry); | ||
102 | ASSERT(p); | ||
103 | m_Cache.RemoveAt(p); | ||
104 | VERIFY(m_Cache.AddHead(pEntry)); | ||
105 | } | ||
106 | |||
107 | virtualBOOL _ReadIn(ARGIDX idx,DATA* data) = 0; | ||
108 | virtual BOOL _WriteOut(ARGIDX idx,DATA* data) = 0; | ||
109 | }; | ||
110 | |||
111 | }; | ||
112 | |||
113 | #endif// __LRUCACHE_H | ||