Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
ConcurrentDictionary.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 using System.Collections;
20 using System.Collections.Generic;
21 using System.Linq;
22 using System.Threading;
23 
24 #if NET35
25 
26 namespace Lucene.Net.Support.Compatibility
27 {
28  /// <summary>
29  /// Support class that emulates the behavior of the ConcurrentDictionary
30  /// from .NET 4.0. This class will, in most cases, perform slightly slower
31  /// than the 4.0 equivalent. Note that all behavior is emulated, which means
32  /// that <see cref="GetEnumerator"/>, <see cref="Keys"/>, and <see cref="Values"/>
33  /// all return a snapshot of the data at the time it was called.
34  /// </summary>
35  [Serializable]
36  public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>
37  {
38  private readonly object _lockObj = new object();
39  private readonly Dictionary<TKey, TValue> _dictInst;
40 
41  public ConcurrentDictionary()
42  : this(16)
43  { }
44 
45  public ConcurrentDictionary(int capacity)
46  : this(capacity, EqualityComparer<TKey>.Default)
47  { }
48 
49  public ConcurrentDictionary(int capacity, IEqualityComparer<TKey> comparer)
50  {
51  _dictInst = new Dictionary<TKey, TValue>(capacity, comparer);
52  }
53 
54  public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> keyValuePairs)
55  : this(16)
56  {
57  foreach(var value in keyValuePairs)
58  {
59  _dictInst.Add(value.Key, value.Value);
60  }
61  }
62 
63  #region Concurrent Dictionary Special Methods
64 
65  public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
66  {
67  lock(_lockObj)
68  {
69  if(_dictInst.ContainsKey(key))
70  {
71  _dictInst[key] = updateValueFactory(key, _dictInst[key]);
72  }
73  else
74  {
75  _dictInst[key] = addValueFactory(key);
76  }
77 
78  return _dictInst[key];
79  }
80  }
81 
82  public TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
83  {
84  lock (_lockObj)
85  {
86  if (_dictInst.ContainsKey(key))
87  {
88  _dictInst[key] = updateValueFactory(key, _dictInst[key]);
89  }
90  else
91  {
92  _dictInst[key] = addValue;
93  }
94 
95  return _dictInst[key];
96  }
97  }
98 
99  public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
100  {
101  lock (_lockObj)
102  {
103  if (!_dictInst.ContainsKey(key))
104  {
105  _dictInst[key] = valueFactory(key);
106  }
107 
108  return _dictInst[key];
109  }
110  }
111 
112  public TValue GetOrAdd(TKey key, TValue value)
113  {
114  lock (_lockObj)
115  {
116  if (!_dictInst.ContainsKey(key))
117  {
118  _dictInst[key] = value;
119  }
120 
121  return _dictInst[key];
122  }
123  }
124 
125  public bool TryAdd(TKey key, TValue value)
126  {
127  lock (_lockObj)
128  {
129  if (_dictInst.ContainsKey(key))
130  {
131  return false;
132  }
133 
134  _dictInst[key] = value;
135  return true;
136  }
137  }
138 
139  public bool TryRemove(TKey key, out TValue value)
140  {
141  lock (_lockObj)
142  {
143  if (_dictInst.ContainsKey(key))
144  {
145  value = _dictInst[key];
146  _dictInst.Remove(key);
147  return true;
148  }
149 
150  value = default(TValue);
151  return false;
152  }
153  }
154 
155  public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)
156  {
157  lock (_lockObj)
158  {
159  if (_dictInst.ContainsKey(key) && _dictInst[key].Equals(comparisonValue))
160  {
161  _dictInst[key] = newValue;
162  return true;
163  }
164 
165  return false;
166  }
167  }
168 
169  #endregion
170 
171  #region IDictionary Methods
172 
173  // .NET4 ConcurrentDictionary returns an enumerator that can enumerate even
174  // if the collection is modified. We can't do that, so create a copy (expensive)
175  public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
176  {
177  lock (_lockObj)
178  {
179  return _dictInst.ToList().GetEnumerator();
180  }
181  }
182 
183  public bool TryGetValue(TKey key, out TValue value)
184  {
185  lock (_lockObj)
186  {
187  return _dictInst.TryGetValue(key, out value);
188  }
189  }
190 
191  IEnumerator IEnumerable.GetEnumerator()
192  {
193  return GetEnumerator();
194  }
195 
196  public void Clear()
197  {
198  lock (_lockObj)
199  {
200  _dictInst.Clear();
201  }
202  }
203 
204  public int Count
205  {
206  get
207  {
208  lock (_lockObj)
209  {
210  return _dictInst.Count;
211  }
212  }
213  }
214 
215  public bool ContainsKey(TKey key)
216  {
217  lock (_lockObj)
218  {
219  return _dictInst.ContainsKey(key);
220  }
221  }
222 
223  public TValue this[TKey key]
224  {
225  get
226  {
227  lock (_lockObj)
228  {
229  return _dictInst[key];
230  }
231  }
232  set
233  {
234  lock (_lockObj)
235  {
236  _dictInst[key] = value;
237  }
238  }
239  }
240 
241  public ICollection<TKey> Keys
242  {
243  get { return _dictInst.Keys.ToArray(); }
244  }
245 
246  public ICollection<TValue> Values
247  {
248  get { return _dictInst.Values.ToArray(); }
249  }
250 
251  #endregion
252 
253  #region Explicit Interface Definitions
254 
255  bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
256  {
257  get { return ((ICollection<KeyValuePair<TKey, TValue>>) _dictInst).IsReadOnly; }
258  }
259 
260  void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
261  {
262  lock (_lockObj)
263  {
264  _dictInst.Add(key, value);
265  }
266  }
267 
268  bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
269  {
270  lock (_lockObj)
271  {
272  return _dictInst.Contains(item);
273  }
274  }
275 
276  bool IDictionary<TKey, TValue>.Remove(TKey key)
277  {
278  lock (_lockObj)
279  {
280  return _dictInst.Remove(key);
281  }
282  }
283 
284  void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
285  {
286  lock (_lockObj)
287  {
288  ((ICollection<KeyValuePair<TKey, TValue>>)_dictInst).Add(item);
289  }
290  }
291 
292  void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
293  {
294  lock (_lockObj)
295  {
296  ((ICollection<KeyValuePair<TKey, TValue>>)_dictInst).CopyTo(array, arrayIndex);
297  }
298  }
299 
300  bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
301  {
302  lock (_lockObj)
303  {
304  return ((ICollection<KeyValuePair<TKey, TValue>>)_dictInst).Remove(item);
305  }
306  }
307 
308  #endregion
309  }
310 }
311 
312 #endif