wasSharp – Blame information for rev 44

Subversion Repositories:
Rev:
Rev Author Line No. Line
22 office 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 //
3 // Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
4 // rights of fair usage, the disclaimer and warranty conditions. //
5 ///////////////////////////////////////////////////////////////////////////
6  
7 using System.Collections;
8 using System.Collections.Generic;
9 using System.Collections.Specialized;
39 office 10 using System.Threading;
22 office 11  
12 namespace wasSharp.Collections.Specialized
13 {
14 ///////////////////////////////////////////////////////////////////////////
15 // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 //
16 ///////////////////////////////////////////////////////////////////////////
17 /// <summary>
18 /// An implementation of an observable Dictionary.
19 /// </summary>
20 /// <typeparam name="K">the key type</typeparam>
21 /// <typeparam name="V">the value type</typeparam>
22 public class ObservableDictionary<K, V> : IDictionary<K, V>, INotifyCollectionChanged
23 {
44 office 24 private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
22 office 25 private readonly Dictionary<K, V> store = new Dictionary<K, V>();
26  
27 public bool IsVirgin { get; private set; } = true;
28  
29 public V this[K key]
30 {
39 office 31 get
32 {
44 office 33 _lock.EnterReadLock();
34 try
35 {
36 return store[key];
37 }
38 finally
39 {
40 if (_lock.IsReadLockHeld) _lock.ExitReadLock();
41 }
39 office 42 }
22 office 43  
39 office 44 set
45 {
44 office 46 _lock.EnterWriteLock();
47 try
48 {
49 store[key] = value;
50 }
51 finally
52 {
53 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
54 }
39 office 55 }
22 office 56 }
57  
58 public int Count => store.Count;
59  
60 public bool IsReadOnly => false;
61  
39 office 62 public ICollection<K> Keys
63 {
64 get
65 {
44 office 66 _lock.EnterReadLock();
67 try
68 {
69 return store.Keys;
70 }
71 finally
72 {
73 if (_lock.IsReadLockHeld) _lock.ExitReadLock();
74 }
39 office 75 }
76 }
22 office 77  
39 office 78 public ICollection<V> Values
79 {
80 get
81 {
44 office 82 _lock.EnterReadLock();
83 try
84 {
85 return store.Values;
86 }
87 finally
88 {
89 if (_lock.IsReadLockHeld) _lock.ExitReadLock();
90 }
39 office 91 }
92 }
22 office 93  
94 public void Add(KeyValuePair<K, V> item)
95 {
44 office 96 _lock.EnterWriteLock();
97 try
98 {
99 ((IDictionary<K, V>) store).Add(item);
100 }
101 finally
102 {
103 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
104 }
22 office 105 IsVirgin = false;
106 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
107 }
108  
109 public void Add(K key, V value)
110 {
44 office 111 _lock.EnterWriteLock();
112 try
113 {
114 store.Add(key, value);
115 }
116 finally
117 {
118 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
119 }
22 office 120 IsVirgin = false;
121 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,
122 new KeyValuePair<K, V>(key, value)));
123 }
124  
125 public void Clear()
126 {
44 office 127 _lock.EnterWriteLock();
128 try
129 {
130 store.Clear();
131 }
132 finally
133 {
134 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
135 }
22 office 136 if (!IsVirgin)
137 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
138 IsVirgin = false;
139 }
140  
141 public bool Contains(KeyValuePair<K, V> item)
142 {
44 office 143 _lock.EnterReadLock();
144 try
145 {
146 return ((IDictionary<K, V>) store).Contains(item);
147 }
148 finally
149 {
150 if (_lock.IsReadLockHeld) _lock.ExitReadLock();
151 }
22 office 152 }
153  
154 public bool ContainsKey(K key)
155 {
44 office 156 _lock.EnterReadLock();
157 try
158 {
159 return store.ContainsKey(key);
160 }
161 finally
162 {
163 if (_lock.IsReadLockHeld) _lock.ExitReadLock();
164 }
22 office 165 }
166  
167 public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex)
168 {
44 office 169 _lock.EnterReadLock();
170 try
171 {
172 ((IDictionary<K, V>) store).CopyTo(array, arrayIndex);
173 }
174 finally
175 {
176 if (_lock.IsReadLockHeld) _lock.ExitReadLock();
177 }
22 office 178 }
179  
180 public IEnumerator<KeyValuePair<K, V>> GetEnumerator()
181 {
44 office 182 _lock.EnterReadLock();
183 try
184 {
185 using (var enumerator = ((IDictionary<K, V>)store).GetEnumerator())
186 {
187 while (enumerator.MoveNext())
188 yield return enumerator.Current;
189 }
190 }
191 finally
192 {
193 if (_lock.IsReadLockHeld) _lock.ExitReadLock();
194 }
22 office 195 }
196  
197 public bool Remove(KeyValuePair<K, V> item)
198 {
44 office 199 _lock.EnterWriteLock();
200 bool removed;
201 try
202 {
203 removed = ((IDictionary<K, V>) store).Remove(item);
204 }
205 finally
206 {
207 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
208 }
22 office 209 IsVirgin = false;
210 if (removed)
211 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
212 return removed;
213 }
214  
215 public bool Remove(K key)
216 {
217 KeyValuePair<K, V> item;
44 office 218 _lock.EnterWriteLock();
219 bool removed;
220 try
221 {
222 if (store.ContainsKey(key))
223 item = new KeyValuePair<K, V>(key, store[key]);
22 office 224  
44 office 225 removed = store.Remove(key);
226 }
227 finally
228 {
229 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
230 }
22 office 231 IsVirgin = false;
232 if (removed)
233 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
234 return removed;
235 }
236  
237 public bool TryGetValue(K key, out V value)
238 {
44 office 239 _lock.EnterReadLock();
240 try
241 {
242 return store.TryGetValue(key, out value);
243 }
244 finally
245 {
246 if (_lock.IsReadLockHeld) _lock.ExitReadLock();
247 }
22 office 248 }
249  
250 IEnumerator IEnumerable.GetEnumerator()
251 {
44 office 252 _lock.EnterReadLock();
253 try
254 {
255 using (var enumerator = ((IDictionary<K, V>)store).GetEnumerator())
256 {
257 while (enumerator.MoveNext())
258 yield return enumerator.Current;
259 }
260 }
261 finally
262 {
263 if (_lock.IsReadLockHeld) _lock.ExitReadLock();
264 }
22 office 265 }
266  
267 public event NotifyCollectionChangedEventHandler CollectionChanged;
268  
269 private void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
270 {
271 CollectionChanged?.Invoke(this, args);
272 }
273 }
27 office 274 }