先是缓存类的接口:
View Code
1 using System;
2
3 namespace ShadowVoice.Dadey.Server
4 {
5 interface IDataCache<TKey, TData>
6 {
7 int Count { get; }
8
9 void Add(TKey key, TData data);
10
11 bool Remove(TKey key);
12 bool Contain(TKey key);
13 bool TryGet(TKey key, out TData data);
14
15 void Clear();
16
17 event Action<TData> OutCache;
18 }
19 }
然后这个是定长缓存代码:
View Code
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace ShadowVoice.Dadey.Server
7 {
8 /// <summary>
9 /// 表示一个固定长度的淘汰式的缓存。当缓存仍有可用空间时,数据将一直存在;当空间溢出时,将自动除去最老的(长期不被访问)的缓存项。
10 /// </summary>
11 /// <typeparam name="TKey">检索缓存数据的键类型。</typeparam>
12 /// <typeparam name="TData">缓存储存的数据项类型。</typeparam>
13 class FixedDataCache<TKey, TData> : IDataCache<TKey, TData>
14 {
15 //*/=========================================================
16 //*/ 内部原理:通过DataItem类型构造一个链表,并保存缓存的数据以及键值。
17 //*/ 当一个缓存项被访问时,将其对应的DataItem项移动至链表的头
18 //*/ 部,当必须要淘汰数据时,将链表尾部指定数量的DataItem剔除,
19 //*/ 直至缓存项的数量小于等于最大数量。
20 //*/=========================================================
21 //*/ 链表模型:以m_latest为头,m_oldest为尾。
22 //*/=========================================================
23
24 DataItem m_latest;
25 DataItem m_oldest;
26 Dictionary<TKey, DataItem> m_cache;
27
28 public int Count { get { return m_cache.Count; } }
29 public uint MaxCount { get; set; }
30
31 public event Action<TData> OutCache;
32
33 const uint DefaultMaxCount = 64;
34 public FixedDataCache(uint max_size)
35 {
36 m_cache = new Dictionary<TKey, DataItem>();
37 MaxCount = max_size;
38 }
39 public FixedDataCache() : this(DefaultMaxCount) { }
40
41 public void Add(TKey key, TData data)
42 {
43 //创建缓存项
44 DataItem item = new DataItem(key, data);
45
46 m_cache.Add(key, item);
47
48 if (Count != 1)
49 {
50 //将数据项插入链表头部
51 item.Next = m_latest;
52 m_latest = m_latest.Previous = item;
53 }
54 else //第一次缓存数据,构造链表
55 m_oldest = m_latest = item;
56
57 //删除最长久没被访问的缓存项直至实际缓存项数量小于等于最大值
58 while (Count > MaxCount)
59 {
60 Remove(m_oldest);
61 }
62 }
63
64 public bool Remove(TKey key)
65 {
66 DataItem item; //尝试获得缓存项并删除
67 if (m_cache.TryGetValue(key, out item))
68 {
69 Remove(item);
70 return true;
71 }
72
73 return false;
74 }
75
76 void Remove(DataItem item)
77 {
78 //将指定缓存项剔出链表
79 item.OutList();
80
81 //检测指定缓存项是否在链表的头部或尾部
82 if (item == m_oldest)
83 m_oldest = item.Previous;
84 if (item == m_latest)
85 m_latest = item.Next;
86
87 //从实际缓存中删除
88 m_cache.Remove(item.Key);
89
90 if (OutCache != null)
91 OutCache(item.Data);
92 }
93
94 public bool Contain(TKey key)
95 {
96 return m_cache.ContainsKey(key);
97 }
98
99 public bool TryGet(TKey key, out TData data)
100 {
101 DataItem item;
102 if (m_cache.TryGetValue(key, out item))
103 {
104 //更新缓存项链表,将被访问的项目移动到链表头部。
105 if (item == m_oldest)
106 m_oldest = item.Previous;
107
108 item.OutList();
109
110 item.Next = m_latest;
111 m_latest = m_latest.Previous = item;
112 data = item.Data;
113
114 return true;
115 }
116
117 data = default(TData);
118 return false;
119 }
120
121 public void Clear()
122 {
123 m_cache.Clear();
124 m_latest = m_oldest = null;
125 }
126
127 /// <summary>
128 /// 表示一个缓存项,实际实现了一个双向链表的节点。
129 /// </summary>
130 class DataItem
131 {
132 public TKey Key;
133 public TData Data;
134
135 public DataItem Previous;
136 public DataItem Next;
137
138 public DataItem(TKey key, TData data)
139 {
140 Key = key;
141 Data = data;
142 }
143
144 /// <summary>
145 /// 将当前的缓存项从链表中除去。
146 /// </summary>
147 public void OutList()
148 {
149 if (Previous != null)
150 Previous.Next = Next;
151 if (Next != null)
152 Next.Previous = Previous;
153 }
154 }
155 }
156 }
这个是时间缓存代码:
View Code
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading;
6 using System.Diagnostics;
7
8 namespace ShadowVoice.Dadey.Server
9 {
10 /// <summary>
11 /// 表示一个动态长度的淘汰式的缓存。任何数据当指定时间内未被访问时,数据项将被从缓存中删除。
12 /// </summary>
13 /// <typeparam name="TKey">检索缓存数据的键类型。</typeparam>
14 /// <typeparam name="TData">缓存储存的数据项类型。</typeparam>
15 class TimedDataCache<TKey, TData> : IDataCache<TKey, TData>
16 {
17 //*/=========================================================
18 //*/ 内部原理:通过DataItem类型构造一个链表,并保存缓存的数据以及键值。
19 //*/ 当一个缓存项被访问时,将其对应的DataItem项移动至链表的头
20 //*/ 部,当类型构造时通过记录一个最小超时间隔,并通过一个Timer
21 //*/ 不停检测最长时间不被访问的缓存是否超时。如果超时,删去数据项。
22 //*/=========================================================
23 //*/ 链表模型:以m_latest为头,m_oldest为尾。
24 //*/=========================================================
25
26 DataItem m_latest;
27 DataItem m_oldest;
28 Dictionary<TKey, DataItem> m_cache;
29 Timer m_timer;
30 long m_timeout_span;
31
32 public event Action<TData> OutCache;
33
34 const int DefaultMinSpan = 10000; //10s
35 public TimedDataCache(int min_span)
36 {
37 m_cache = new Dictionary<TKey, DataItem>();
38
39 TimeoutSpan = min_span;
40 m_timer = new Timer(Timer_Tick, null, min_span, min_span);
41 }
42 public TimedDataCache() : this(DefaultMinSpan) { }
43
44 public int Count { get { return m_cache.Count; } }
45 public long TimeoutSpan
46 {
47 get { return m_timeout_span * 1000 / Stopwatch.Frequency; }
48 set { m_timeout_span = value * Stopwatch.Frequency / 1000; }
49 }
50
51 public void Add(TKey key, TData data)
52 {
53 //创建缓存项
54 DataItem item = new DataItem(key, data);
55
56 m_cache.Add(key, item);
57
58 if (Count != 1)
59 {
60 //将数据项插入链表头部
61 item.Next = m_latest;
62 m_latest = m_latest.Previous = item;
63 }
64 else //第一次缓存数据,构造链表
65 m_oldest = m_latest = item;
66 }
67
68 public bool Remove(TKey key)
69 {
70 DataItem item; //尝试获得缓存项并删除
71 if (m_cache.TryGetValue(key, out item))
72 {
73 Remove(item);
74 return true;
75 }
76
77 return false;
78 }
79
80 void Remove(DataItem item)
81 {
82 //将指定缓存项剔出链表
83 item.OutList();
84
85 //检测指定缓存项是否在链表的头部或尾部
86 if (item == m_oldest)
87 m_oldest = item.Previous;
88 if (item == m_latest)
89 m_latest = item.Next;
90
91 //从实际缓存中删除
92 m_cache.Remove(item.Key);
93
94 if (OutCache != null)
95 OutCache(item.Data);
96 }
97
98 public bool Contain(TKey key)
99 {
100 return m_cache.ContainsKey(key);
101 }
102
103 public bool TryGet(TKey key, out TData data)
104 {
105 DataItem item;
106 if (m_cache.TryGetValue(key, out item))
107 {
108 //更新缓存项链表,将被访问的项目移动到链表头部。
109 if (item == m_oldest)
110 m_oldest = item.Previous;
111
112 item.OutList();
113 item.RefreshTick();
114
115 item.Next = m_latest;
116 m_latest = m_latest.Previous = item;
117 data = item.Data;
118
119 return true;
120 }
121
122 data = default(TData);
123 return false;
124 }
125
126 public void Clear()
127 {
128 m_cache.Clear();
129 m_latest = m_oldest = null;
130 }
131
132 public void SetMinTimeSpan(int span)
133 {
134 m_timer.Change(span, span);
135 }
136
137 void Timer_Tick(object nothing)
138 {
139 if (Count != 0)
140 {
141 long now = Stopwatch.GetTimestamp();
142
143 lock (this)
144 {
145 while (now - m_oldest.Tick > m_timeout_span && m_oldest != null)
146 Remove(m_oldest);
147 }
148 }
149 }
150
151 /// <summary>
152 /// 表示一个缓存项,实际实现了一个双向链表的节点。
153 /// </summary>
154 class DataItem
155 {
156 public TKey Key;
157 public TData Data;
158
159 public long Tick;
160 public DataItem Previous;
161 public DataItem Next;
162
163 public DataItem(TKey key, TData data)
164 {
165 Key = key;
166 Data = data;
167
168 RefreshTick();
169 }
170
171 public void RefreshTick()
172 {
173 Tick = Stopwatch.GetTimestamp();
174 }
175
176 /// <summary>
177 /// 将当前的缓存项从链表中除去。
178 /// </summary>
179 public void OutList()
180 {
181 if (Previous != null)
182 Previous.Next = Next;
183 if (Next != null)
184 Next.Previous = Previous;
185 }
186 }
187 }
188 }

浙公网安备 33010602011771号