/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
#if NET35
namespace Lucene.Net.Support.Compatibility
{
///
/// Support class that emulates the behavior of the ConcurrentDictionary
/// from .NET 4.0. This class will, in most cases, perform slightly slower
/// than the 4.0 equivalent. Note that all behavior is emulated, which means
/// that , , and
/// all return a snapshot of the data at the time it was called.
///
[Serializable]
public class ConcurrentDictionary : IDictionary
{
private readonly object _lockObj = new object();
private readonly Dictionary _dictInst;
public ConcurrentDictionary()
: this(16)
{ }
public ConcurrentDictionary(int capacity)
: this(capacity, EqualityComparer.Default)
{ }
public ConcurrentDictionary(int capacity, IEqualityComparer comparer)
{
_dictInst = new Dictionary(capacity, comparer);
}
public ConcurrentDictionary(IEnumerable> keyValuePairs)
: this(16)
{
foreach(var value in keyValuePairs)
{
_dictInst.Add(value.Key, value.Value);
}
}
#region Concurrent Dictionary Special Methods
public TValue AddOrUpdate(TKey key, Func addValueFactory, Func updateValueFactory)
{
lock(_lockObj)
{
if(_dictInst.ContainsKey(key))
{
_dictInst[key] = updateValueFactory(key, _dictInst[key]);
}
else
{
_dictInst[key] = addValueFactory(key);
}
return _dictInst[key];
}
}
public TValue AddOrUpdate(TKey key, TValue addValue, Func updateValueFactory)
{
lock (_lockObj)
{
if (_dictInst.ContainsKey(key))
{
_dictInst[key] = updateValueFactory(key, _dictInst[key]);
}
else
{
_dictInst[key] = addValue;
}
return _dictInst[key];
}
}
public TValue GetOrAdd(TKey key, Func valueFactory)
{
lock (_lockObj)
{
if (!_dictInst.ContainsKey(key))
{
_dictInst[key] = valueFactory(key);
}
return _dictInst[key];
}
}
public TValue GetOrAdd(TKey key, TValue value)
{
lock (_lockObj)
{
if (!_dictInst.ContainsKey(key))
{
_dictInst[key] = value;
}
return _dictInst[key];
}
}
public bool TryAdd(TKey key, TValue value)
{
lock (_lockObj)
{
if (_dictInst.ContainsKey(key))
{
return false;
}
_dictInst[key] = value;
return true;
}
}
public bool TryRemove(TKey key, out TValue value)
{
lock (_lockObj)
{
if (_dictInst.ContainsKey(key))
{
value = _dictInst[key];
_dictInst.Remove(key);
return true;
}
value = default(TValue);
return false;
}
}
public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)
{
lock (_lockObj)
{
if (_dictInst.ContainsKey(key) && _dictInst[key].Equals(comparisonValue))
{
_dictInst[key] = newValue;
return true;
}
return false;
}
}
#endregion
#region IDictionary Methods
// .NET4 ConcurrentDictionary returns an enumerator that can enumerate even
// if the collection is modified. We can't do that, so create a copy (expensive)
public IEnumerator> GetEnumerator()
{
lock (_lockObj)
{
return _dictInst.ToList().GetEnumerator();
}
}
public bool TryGetValue(TKey key, out TValue value)
{
lock (_lockObj)
{
return _dictInst.TryGetValue(key, out value);
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Clear()
{
lock (_lockObj)
{
_dictInst.Clear();
}
}
public int Count
{
get
{
lock (_lockObj)
{
return _dictInst.Count;
}
}
}
public bool ContainsKey(TKey key)
{
lock (_lockObj)
{
return _dictInst.ContainsKey(key);
}
}
public TValue this[TKey key]
{
get
{
lock (_lockObj)
{
return _dictInst[key];
}
}
set
{
lock (_lockObj)
{
_dictInst[key] = value;
}
}
}
public ICollection Keys
{
get { return _dictInst.Keys.ToArray(); }
}
public ICollection Values
{
get { return _dictInst.Values.ToArray(); }
}
#endregion
#region Explicit Interface Definitions
bool ICollection>.IsReadOnly
{
get { return ((ICollection>) _dictInst).IsReadOnly; }
}
void IDictionary.Add(TKey key, TValue value)
{
lock (_lockObj)
{
_dictInst.Add(key, value);
}
}
bool ICollection>.Contains(KeyValuePair item)
{
lock (_lockObj)
{
return _dictInst.Contains(item);
}
}
bool IDictionary.Remove(TKey key)
{
lock (_lockObj)
{
return _dictInst.Remove(key);
}
}
void ICollection>.Add(KeyValuePair item)
{
lock (_lockObj)
{
((ICollection>)_dictInst).Add(item);
}
}
void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex)
{
lock (_lockObj)
{
((ICollection>)_dictInst).CopyTo(array, arrayIndex);
}
}
bool ICollection>.Remove(KeyValuePair item)
{
lock (_lockObj)
{
return ((ICollection>)_dictInst).Remove(item);
}
}
#endregion
}
}
#endif