PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/mcs/class/corlib/System.Collections.Concurrent/ConcurrentDictionary.cs

https://github.com/sdether/mono
C# | 438 lines | 328 code | 81 blank | 29 comment | 14 complexity | c10ba54324fbe5c732dd78db5986c400 MD5 | raw file
  1. // ConcurrentDictionary.cs
  2. //
  3. // Copyright (c) 2009 Jérémie "Garuma" Laval
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. //
  24. #if NET_4_0 || BOOTSTRAP_NET_4_0
  25. using System;
  26. using System.Threading;
  27. using System.Collections;
  28. using System.Collections.Generic;
  29. using System.Runtime.Serialization;
  30. namespace System.Collections.Concurrent
  31. {
  32. public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>,
  33. ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>,
  34. IDictionary, ICollection, IEnumerable
  35. {
  36. IEqualityComparer<TKey> comparer;
  37. SplitOrderedList<KeyValuePair<TKey, TValue>> internalDictionary = new SplitOrderedList<KeyValuePair<TKey, TValue>> ();
  38. public ConcurrentDictionary () : this (EqualityComparer<TKey>.Default)
  39. {
  40. }
  41. public ConcurrentDictionary (IEnumerable<KeyValuePair<TKey, TValue>> values)
  42. : this (values, EqualityComparer<TKey>.Default)
  43. {
  44. foreach (KeyValuePair<TKey, TValue> pair in values)
  45. Add (pair.Key, pair.Value);
  46. }
  47. public ConcurrentDictionary (IEqualityComparer<TKey> comparer)
  48. {
  49. this.comparer = comparer;
  50. }
  51. public ConcurrentDictionary (IEnumerable<KeyValuePair<TKey, TValue>> values, IEqualityComparer<TKey> comparer)
  52. : this (comparer)
  53. {
  54. foreach (KeyValuePair<TKey, TValue> pair in values)
  55. Add (pair.Key, pair.Value);
  56. }
  57. // Parameters unused
  58. public ConcurrentDictionary (int concurrencyLevel, int capacity)
  59. : this (EqualityComparer<TKey>.Default)
  60. {
  61. }
  62. public ConcurrentDictionary (int concurrencyLevel,
  63. IEnumerable<KeyValuePair<TKey, TValue>> values,
  64. IEqualityComparer<TKey> comparer)
  65. : this (values, comparer)
  66. {
  67. }
  68. // Parameters unused
  69. public ConcurrentDictionary (int concurrencyLevel, int capacity, IEqualityComparer<TKey> comparer)
  70. : this (comparer)
  71. {
  72. }
  73. void Add (TKey key, TValue value)
  74. {
  75. while (!TryAdd (key, value));
  76. }
  77. void IDictionary<TKey, TValue>.Add (TKey key, TValue value)
  78. {
  79. Add (key, value);
  80. }
  81. public bool TryAdd (TKey key, TValue value)
  82. {
  83. return internalDictionary.Insert (Hash (key), Make (key, value));
  84. }
  85. void ICollection<KeyValuePair<TKey,TValue>>.Add (KeyValuePair<TKey, TValue> pair)
  86. {
  87. Add (pair.Key, pair.Value);
  88. }
  89. public TValue AddOrUpdate (TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
  90. {
  91. return internalDictionary.InsertOrUpdate (Hash (key),
  92. () => Make (key, addValueFactory (key)),
  93. (e) => Make (key, updateValueFactory (key, e.Value))).Value;
  94. }
  95. public TValue AddOrUpdate (TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
  96. {
  97. return AddOrUpdate (key, (_) => addValue, updateValueFactory);
  98. }
  99. TValue AddOrUpdate (TKey key, TValue addValue, TValue updateValue)
  100. {
  101. return internalDictionary.InsertOrUpdate (Hash (key),
  102. Make (key, addValue),
  103. Make (key, updateValue)).Value;
  104. }
  105. TValue GetValue (TKey key)
  106. {
  107. TValue temp;
  108. if (!TryGetValue (key, out temp))
  109. // TODO: find a correct Exception
  110. throw new ArgumentException ("Not a valid key for this dictionary", "key");
  111. return temp;
  112. }
  113. public bool TryGetValue (TKey key, out TValue value)
  114. {
  115. KeyValuePair<TKey, TValue> pair;
  116. bool result = internalDictionary.Find (Hash (key), out pair);
  117. value = pair.Value;
  118. return result;
  119. }
  120. public bool TryUpdate (TKey key, TValue newValue, TValue comparand)
  121. {
  122. return internalDictionary.CompareExchange (Hash (key), Make (key, newValue), (e) => e.Value.Equals (comparand));
  123. }
  124. public TValue this[TKey key] {
  125. get {
  126. return GetValue (key);
  127. }
  128. set {
  129. AddOrUpdate (key, value, value);
  130. }
  131. }
  132. public TValue GetOrAdd (TKey key, Func<TKey, TValue> valueFactory)
  133. {
  134. return internalDictionary.InsertOrGet (Hash (key), Make (key, default(TValue)), () => Make (key, valueFactory (key))).Value;
  135. }
  136. public TValue GetOrAdd (TKey key, TValue value)
  137. {
  138. return internalDictionary.InsertOrGet (Hash (key), Make (key, value), null).Value;
  139. }
  140. public bool TryRemove (TKey key, out TValue value)
  141. {
  142. KeyValuePair<TKey, TValue> data;
  143. bool result = internalDictionary.Delete (Hash (key), out data);
  144. value = data.Value;
  145. return result;
  146. }
  147. bool Remove (TKey key)
  148. {
  149. TValue dummy;
  150. return TryRemove (key, out dummy);
  151. }
  152. bool IDictionary<TKey, TValue>.Remove (TKey key)
  153. {
  154. return Remove (key);
  155. }
  156. bool ICollection<KeyValuePair<TKey,TValue>>.Remove (KeyValuePair<TKey,TValue> pair)
  157. {
  158. return Remove (pair.Key);
  159. }
  160. public bool ContainsKey (TKey key)
  161. {
  162. KeyValuePair<TKey, TValue> dummy;
  163. return internalDictionary.Find (Hash (key), out dummy);
  164. }
  165. bool IDictionary.Contains (object key)
  166. {
  167. if (!(key is TKey))
  168. return false;
  169. return ContainsKey ((TKey)key);
  170. }
  171. void IDictionary.Remove (object key)
  172. {
  173. if (!(key is TKey))
  174. return;
  175. Remove ((TKey)key);
  176. }
  177. object IDictionary.this [object key]
  178. {
  179. get {
  180. if (!(key is TKey))
  181. throw new ArgumentException ("key isn't of correct type", "key");
  182. return this[(TKey)key];
  183. }
  184. set {
  185. if (!(key is TKey) || !(value is TValue))
  186. throw new ArgumentException ("key or value aren't of correct type");
  187. this[(TKey)key] = (TValue)value;
  188. }
  189. }
  190. void IDictionary.Add (object key, object value)
  191. {
  192. if (!(key is TKey) || !(value is TValue))
  193. throw new ArgumentException ("key or value aren't of correct type");
  194. Add ((TKey)key, (TValue)value);
  195. }
  196. bool ICollection<KeyValuePair<TKey,TValue>>.Contains (KeyValuePair<TKey, TValue> pair)
  197. {
  198. return ContainsKey (pair.Key);
  199. }
  200. public KeyValuePair<TKey,TValue>[] ToArray ()
  201. {
  202. // This is most certainly not optimum but there is
  203. // not a lot of possibilities
  204. return new List<KeyValuePair<TKey,TValue>> (this).ToArray ();
  205. }
  206. public void Clear()
  207. {
  208. // Pronk
  209. internalDictionary = new SplitOrderedList<KeyValuePair<TKey, TValue>> ();
  210. }
  211. public int Count {
  212. get {
  213. return internalDictionary.Count;
  214. }
  215. }
  216. public bool IsEmpty {
  217. get {
  218. return Count == 0;
  219. }
  220. }
  221. bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly {
  222. get {
  223. return false;
  224. }
  225. }
  226. bool IDictionary.IsReadOnly {
  227. get {
  228. return false;
  229. }
  230. }
  231. public ICollection<TKey> Keys {
  232. get {
  233. return GetPart<TKey> ((kvp) => kvp.Key);
  234. }
  235. }
  236. public ICollection<TValue> Values {
  237. get {
  238. return GetPart<TValue> ((kvp) => kvp.Value);
  239. }
  240. }
  241. ICollection IDictionary.Keys {
  242. get {
  243. return (ICollection)Keys;
  244. }
  245. }
  246. ICollection IDictionary.Values {
  247. get {
  248. return (ICollection)Values;
  249. }
  250. }
  251. ICollection<T> GetPart<T> (Func<KeyValuePair<TKey, TValue>, T> extractor)
  252. {
  253. List<T> temp = new List<T> ();
  254. foreach (KeyValuePair<TKey, TValue> kvp in this)
  255. temp.Add (extractor (kvp));
  256. return temp.AsReadOnly ();
  257. }
  258. void ICollection.CopyTo (Array array, int startIndex)
  259. {
  260. KeyValuePair<TKey, TValue>[] arr = array as KeyValuePair<TKey, TValue>[];
  261. if (arr == null)
  262. return;
  263. CopyTo (arr, startIndex, Count);
  264. }
  265. void CopyTo (KeyValuePair<TKey, TValue>[] array, int startIndex)
  266. {
  267. CopyTo (array, startIndex, Count);
  268. }
  269. void ICollection<KeyValuePair<TKey, TValue>>.CopyTo (KeyValuePair<TKey, TValue>[] array, int startIndex)
  270. {
  271. CopyTo (array, startIndex);
  272. }
  273. void CopyTo (KeyValuePair<TKey, TValue>[] array, int startIndex, int num)
  274. {
  275. foreach (var kvp in this) {
  276. array [startIndex++] = kvp;
  277. if (--num <= 0)
  278. return;
  279. }
  280. }
  281. public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator ()
  282. {
  283. return GetEnumeratorInternal ();
  284. }
  285. IEnumerator IEnumerable.GetEnumerator ()
  286. {
  287. return (IEnumerator)GetEnumeratorInternal ();
  288. }
  289. IEnumerator<KeyValuePair<TKey, TValue>> GetEnumeratorInternal ()
  290. {
  291. return internalDictionary.GetEnumerator ();
  292. }
  293. IDictionaryEnumerator IDictionary.GetEnumerator ()
  294. {
  295. return new ConcurrentDictionaryEnumerator (GetEnumeratorInternal ());
  296. }
  297. class ConcurrentDictionaryEnumerator : IDictionaryEnumerator
  298. {
  299. IEnumerator<KeyValuePair<TKey, TValue>> internalEnum;
  300. public ConcurrentDictionaryEnumerator (IEnumerator<KeyValuePair<TKey, TValue>> internalEnum)
  301. {
  302. this.internalEnum = internalEnum;
  303. }
  304. public bool MoveNext ()
  305. {
  306. return internalEnum.MoveNext ();
  307. }
  308. public void Reset ()
  309. {
  310. internalEnum.Reset ();
  311. }
  312. public object Current {
  313. get {
  314. return Entry;
  315. }
  316. }
  317. public DictionaryEntry Entry {
  318. get {
  319. KeyValuePair<TKey, TValue> current = internalEnum.Current;
  320. return new DictionaryEntry (current.Key, current.Value);
  321. }
  322. }
  323. public object Key {
  324. get {
  325. return internalEnum.Current.Key;
  326. }
  327. }
  328. public object Value {
  329. get {
  330. return internalEnum.Current.Value;
  331. }
  332. }
  333. }
  334. object ICollection.SyncRoot {
  335. get {
  336. return this;
  337. }
  338. }
  339. bool IDictionary.IsFixedSize {
  340. get {
  341. return false;
  342. }
  343. }
  344. bool ICollection.IsSynchronized {
  345. get { return true; }
  346. }
  347. static KeyValuePair<U, V> Make<U, V> (U key, V value)
  348. {
  349. return new KeyValuePair<U, V> (key, value);
  350. }
  351. uint Hash (TKey key)
  352. {
  353. return (uint)comparer.GetHashCode (key);
  354. }
  355. }
  356. }
  357. #endif