1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
/******************************************************************************
*
* $Id:$
*
* Copyright (C) 1997-2012 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
#ifndef OBJCACHE_H
#define OBJCACHE_H
//#define CACHE_TEST
//#define CACHE_DEBUG
#define CACHE_STATS
/** @brief Cache for objects.
*
* This cache is used to decide which objects should remain in
* memory. It uses a least recently used policy (LRU) to decide
* which object should make room for a new object when the cache
* is full. An object should be added using add(), and then use()
* should be called when the object is used.
*/
class ObjCache
{
private:
struct CacheNode
{
CacheNode() : next(-1), prev(-1), obj(0) {}
int next;
int prev;
void *obj;
};
struct HashNode
{
HashNode() : head(-1), nextHash(-1), index(-1), obj(0) {}
int head;
int nextHash;
int index;
void *obj;
};
public:
/*! Creates the cache. The number of elements in the cache is 2 to
* the power of \a logSize.
*/
ObjCache(unsigned int logSize);
/*! Deletes the cache and free all internal data-structures used. */
~ObjCache();
/*! Adds \a obj to the cache. When victim is not null, this object is
* removed from the cache to make room for \a obj.
* Returns a handle to the object, which can be used by the use()
* function, each time the object is used.
*/
int add(void *obj,void **victim);
/*! Indicates that this object is used. This will move the object
* to the front of the internal LRU list to make sure it is removed last.
* The parameter \a handle is returned when called add().
*/
void use(int handle)
{
if (handle==m_lastHandle) return;
m_lastHandle = handle;
m_hits++;
moveToFront(handle);
}
/*! Removes the item identified by \a handle from the cache.
* @see add()
*/
void del(int handle);
/*! Debug function. Prints the LRU list */
void printLRU();
/*! Print miss/hits statistics */
void printStats();
/*! total size of the cache */
int size() const { return m_size; }
/*! number of elements in the cache */
int count() const { return m_count; }
int hits() const
{
return m_hits;
}
int misses() const
{
return m_misses;
}
private:
void moveToFront(int index);
unsigned int hash(void *addr);
HashNode *hashFind(void *obj);
HashNode *hashInsert(void *obj);
void hashRemove(void *obj);
CacheNode *m_cache;
HashNode *m_hash;
int m_head;
int m_tail;
int m_size;
int m_count;
int m_freeHashNodes;
int m_freeCacheNodes;
int m_lastHandle;
int m_misses;
int m_hits;
};
#endif // OBJCACHE_H
|