Posted By

jmillerit on 08/06/10


Tagged


Versions (?)

Who likes this?

2 people have marked this snippet as a favorite

Vordreller
Tyster


Synchronized Dictionary


 / Published in: C#
 

  1. /// Synchronized Dictionary
  2. /// Dictionary that uses ReaderWriterLockSlim to syncronize all read and writes to the underlying Dictionary
  3.  
  4. using System;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Threading;
  9. namespace Core.Collections.Generic {
  10. /// <summary>
  11. /// Dictionary that uses ReaderWriterLockSlim to syncronize all read and writes to the underlying Dictionary
  12. /// </summary>
  13. /// <typeparam name="TKey"></typeparam>
  14. /// <typeparam name="TValue"></typeparam>
  15. [Serializable]
  16. public class SynchronizedDictionary<TKey,TValue>:IDictionary<TKey,TValue>,IDisposable {
  17.  
  18. Dictionary<TKey,TValue> _dictionary;
  19.  
  20. [NonSerialized]
  21. ReaderWriterLockSlim _lock;
  22.  
  23. public SynchronizedDictionary() {
  24. _dictionary = new Dictionary<TKey,TValue>();
  25. }
  26. public SynchronizedDictionary(IDictionary<TKey,TValue> dictionary) {
  27. _dictionary = new Dictionary<TKey,TValue>(dictionary);
  28. }
  29. public SynchronizedDictionary(IEqualityComparer<TKey> comparer) {
  30. _dictionary = new Dictionary<TKey,TValue>(comparer);
  31. }
  32. public SynchronizedDictionary(int capacity) {
  33. _dictionary = new Dictionary<TKey,TValue>(capacity);
  34. }
  35. public SynchronizedDictionary(IDictionary<TKey,TValue> dictionary,IEqualityComparer<TKey> comparer) {
  36. _dictionary = new Dictionary<TKey,TValue>(dictionary,comparer);
  37. }
  38. public SynchronizedDictionary(int capacity,IEqualityComparer<TKey> comparer) {
  39. _dictionary = new Dictionary<TKey,TValue>(capacity,comparer);
  40. }
  41. protected ReaderWriterLockSlim Lock {
  42. get {
  43. if(_lock == null) {
  44. Interlocked.CompareExchange(ref _lock,new ReaderWriterLockSlim(),null);
  45. }
  46. return _lock;
  47. }
  48. }
  49. public void EnterReadLock() {
  50. Lock.EnterReadLock();
  51. }
  52. public void ExitReadLock() {
  53. Lock.ExitReadLock();
  54. }
  55. public void EnterWriteLock() {
  56. Lock.EnterWriteLock();
  57. }
  58. public void ExitWriteLock() {
  59. Lock.ExitWriteLock();
  60. }
  61. public void EnterUpgradeableReadLock() {
  62. Lock.EnterUpgradeableReadLock();
  63. }
  64. public void ExitUpgradeableReadLock() {
  65. Lock.ExitUpgradeableReadLock();
  66. }
  67. protected Dictionary<TKey,TValue> Dictionary {
  68. get {
  69. return _dictionary;
  70. }
  71. }
  72. public TValue GetAdd(TKey key,Func<TValue> addfunction) {
  73.  
  74. if(addfunction == null)
  75. throw new ArgumentNullException("Func<TValue> addfunction");
  76.  
  77. try {
  78. EnterUpgradeableReadLock();
  79.  
  80. if(!_dictionary.ContainsKey(key)) {
  81. try {
  82. EnterWriteLock();
  83.  
  84. TValue value = addfunction();
  85.  
  86. _dictionary.Add(key,value);
  87. return value;
  88. }
  89. finally {
  90. ExitWriteLock();
  91. }
  92. }
  93. else {
  94. return _dictionary[key];
  95. }
  96. }
  97. finally {
  98. ExitUpgradeableReadLock();
  99. }
  100. }
  101. public void Add(TKey key,TValue value) {
  102. try {
  103. EnterWriteLock();
  104. _dictionary.Add(key,value);
  105. }
  106. finally {
  107. ExitWriteLock();
  108. }
  109. }
  110. public void Add(KeyValuePair<TKey,TValue> item) {
  111. try {
  112. EnterWriteLock();
  113. _dictionary.Add(item.Key,item.Value);
  114. }
  115. finally {
  116. ExitWriteLock();
  117. }
  118. }
  119. public bool Add(TKey key,TValue value,bool throwOnNotFound) {
  120. try {
  121. EnterUpgradeableReadLock();
  122. if(!_dictionary.ContainsKey(key)) {
  123. try {
  124. EnterWriteLock();
  125. _dictionary.Add(key,value);
  126. return true;
  127. }
  128. finally {
  129. ExitWriteLock();
  130. }
  131. }
  132. else {
  133. if(throwOnNotFound)
  134. throw new ArgumentNullException();
  135. else
  136. return false;
  137. }
  138. }
  139. finally {
  140. ExitUpgradeableReadLock();
  141. }
  142. }
  143. public bool ContainsKey(TKey key) {
  144. try {
  145. EnterReadLock();
  146. return _dictionary.ContainsKey(key);
  147. }
  148. finally {
  149. ExitReadLock();
  150. }
  151. }
  152. public bool Contains(KeyValuePair<TKey,TValue> item) {
  153. try {
  154. EnterReadLock();
  155. return _dictionary.Contains(item);
  156. }
  157. finally {
  158. ExitReadLock();
  159. }
  160. }
  161. public TKey[] KeysToArray() {
  162. try {
  163. EnterReadLock();
  164. return _dictionary.Keys.ToArray();
  165. }
  166. finally {
  167. ExitReadLock();
  168. }
  169. }
  170. public ICollection<TKey> Keys {
  171. get {
  172. return _dictionary.Keys;
  173. }
  174. }
  175. public bool Remove(TKey key) {
  176. try {
  177. EnterWriteLock();
  178. return _dictionary.Remove(key);
  179. }
  180. finally {
  181. ExitWriteLock();
  182. }
  183. }
  184. public bool Remove(KeyValuePair<TKey,TValue> item) {
  185. try {
  186. EnterWriteLock();
  187. return _dictionary.Remove(item.Key);
  188. }
  189. finally {
  190. ExitWriteLock();
  191. }
  192. }
  193. public bool TryGetValue(TKey key,out TValue value) {
  194. try {
  195. EnterReadLock();
  196. return _dictionary.TryGetValue(key,out value);
  197. }
  198. finally {
  199. ExitReadLock();
  200. }
  201. }
  202. public TValue[] ValuesToArray() {
  203. try {
  204. EnterReadLock();
  205. return _dictionary.Values.ToArray();
  206. }
  207. finally {
  208. ExitReadLock();
  209. }
  210. }
  211. public ICollection<TValue> Values {
  212. get {
  213. return _dictionary.Values;
  214. }
  215. }
  216.  
  217. public TValue this[TKey key] {
  218. get {
  219. try {
  220. EnterReadLock();
  221. return _dictionary[key];
  222. }
  223. finally {
  224. ExitReadLock();
  225. }
  226. }
  227. set {
  228. try {
  229. EnterWriteLock();
  230. _dictionary[key] = value;
  231. }
  232. finally {
  233. ExitWriteLock();
  234. }
  235. }
  236. }
  237. public void Clear() {
  238. try {
  239. EnterWriteLock();
  240. _dictionary.Clear();
  241. }
  242. finally {
  243. ExitWriteLock();
  244. }
  245. }
  246. public void CopyTo(KeyValuePair<TKey,TValue>[] array,int arrayIndex) {
  247. try {
  248. EnterReadLock();
  249.  
  250. for(int i = 0;i < _dictionary.Count;i++) {
  251. array.SetValue(_dictionary.ElementAt(i),arrayIndex);
  252. }
  253. }
  254. finally {
  255. ExitReadLock();
  256. }
  257. }
  258. public int Count {
  259. get {
  260. try {
  261. EnterReadLock();
  262. return _dictionary.Count;
  263. }
  264. finally {
  265. ExitReadLock();
  266. }
  267. }
  268. }
  269. public bool IsReadOnly {
  270. get {
  271. return false;
  272. }
  273. }
  274. public bool IsSynchronized {
  275. get {
  276. return true;
  277. }
  278. }
  279. public IEnumerator<KeyValuePair<TKey,TValue>> GetEnumerator() {
  280. EnterReadLock();
  281. try {
  282. return _dictionary.GetEnumerator();
  283. }
  284. finally {
  285. ExitReadLock();
  286. }
  287. }
  288. IEnumerator IEnumerable.GetEnumerator() {
  289. return this.GetEnumerator();
  290. }
  291.  
  292. protected bool IsDisposed { get; set; }
  293. public virtual void Dispose() {
  294. if(IsDisposed)
  295. throw new ObjectDisposedException(this.GetType().Name);
  296. try {
  297. this.Dispose(true);
  298. }
  299. finally {
  300. GC.SuppressFinalize(this);
  301. }
  302. }
  303. protected virtual void Dispose(bool disposing) {
  304. try {
  305. if(!IsDisposed) {
  306. if(disposing) {
  307. if(_lock != null) {
  308. _lock.Dispose();
  309. _lock = null;
  310. }
  311. }
  312. }
  313. }
  314. finally {
  315. this.IsDisposed = true;
  316. }
  317. }
  318. //Only add Finalizer in you need to dispose of resources with out call Dispose() directly
  319. ~SynchronizedDictionary() {
  320. Dispose(!IsDisposed);
  321. }
  322. }
  323. }
  324.  

Report this snippet  

Comments

RSS Icon Subscribe to comments
Posted By: RomanLevchenko on November 26, 2012

For me it looks like GetEnumerator returns a non-threadsafe IEnumerator.

You need to login to post a comment.