/*
Copyright 2008 The 'A Concurrent Hashtable' development team
(http://www.codeplex.com/CH/People/ProjectPeople.aspx)
This library is licensed under the GNU Library General Public License (LGPL). You should
have received a copy of the license along with the source code. If not, an online copy
of the license can be found at http://www.codeplex.com/CH/license.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Runtime.Serialization;
using System.Security;
namespace Orvid.Concurrent.Collections
{
///
/// Represents a thread-safe collection of key-value pairs that can be accessed
/// by multiple threads concurrently and has weak references to the values.
///
/// The type of the keys in this dictionary.
/// The type of the values in this dictionary. This must be a reference type.
///
/// Whenever any of the values held by this dictionary is garbage collected the key-value pair holding the value will be removed from the dictionary.
///
#if !SILVERLIGHT
[Serializable]
#endif
public class WeakDictionary : DictionaryBase
#if !SILVERLIGHT
, ISerializable
#endif
where TValue : class
{
sealed class InternalWeakDictionary :
InternalWeakDictionaryWeakValueBase<
StrongKey,
TStrongKey,
TValue,
StrongKey
>
{
public InternalWeakDictionary(int concurrencyLevel, int capacity, KeyComparer keyComparer)
: base(concurrencyLevel, capacity, keyComparer)
{
_comparer = keyComparer;
MaintenanceWorker.Register(this);
}
public InternalWeakDictionary(KeyComparer keyComparer)
: base(keyComparer)
{
_comparer = keyComparer;
MaintenanceWorker.Register(this);
}
public KeyComparer _comparer;
protected override StrongKey FromExternalKeyToSearchKey(TStrongKey externalKey)
{ return new StrongKey(externalKey); }
protected override StrongKey FromExternalKeyToStorageKey(TStrongKey externalKey)
{ return new StrongKey(externalKey); }
protected override StrongKey FromStackKeyToSearchKey(StrongKey externalKey)
{ return externalKey; }
protected override StrongKey FromStackKeyToStorageKey(StrongKey externalKey)
{ return externalKey; }
protected override bool FromInternalKeyToExternalKey(StrongKey internalKey, out TStrongKey externalKey)
{
externalKey = internalKey._element;
return true;
}
protected override bool FromInternalKeyToStackKey(StrongKey internalKey, out StrongKey externalKey)
{
externalKey = internalKey;
return true;
}
}
readonly InternalWeakDictionary _internalDictionary;
protected override IDictionary InternalDictionary
{ get { return _internalDictionary; } }
#if !SILVERLIGHT
WeakDictionary(SerializationInfo serializationInfo, StreamingContext streamingContext)
{
var comparer = (KeyComparer)serializationInfo.GetValue("Comparer", typeof(KeyComparer));
var items = (List>)serializationInfo.GetValue("Items", typeof(List>));
_internalDictionary = new InternalWeakDictionary(comparer);
_internalDictionary.InsertContents(items);
}
#region ISerializable Members
[SecurityCritical]
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Comparer", _internalDictionary._comparer);
info.AddValue("Items", _internalDictionary.GetContents());
}
#endregion
#endif
public WeakDictionary()
: this(EqualityComparer.Default)
{}
public WeakDictionary(IEqualityComparer strongKeyComparer)
: this(Enumerable.Empty>(), strongKeyComparer)
{}
public WeakDictionary(IEnumerable> collection)
: this(collection, EqualityComparer.Default)
{}
public WeakDictionary(IEnumerable> collection, IEqualityComparer strongKeyComparer)
{
_internalDictionary =
new InternalWeakDictionary(
new KeyComparer(strongKeyComparer)
)
;
_internalDictionary.InsertContents(collection);
}
public WeakDictionary(int concurrencyLevel, int capacity)
: this(concurrencyLevel, capacity, EqualityComparer.Default)
{}
public WeakDictionary(int concurrencyLevel, IEnumerable> collection, IEqualityComparer strongKeyComparer)
{
var contentsList = collection.ToList();
_internalDictionary =
new InternalWeakDictionary(
concurrencyLevel,
contentsList.Count,
new KeyComparer(strongKeyComparer)
)
;
_internalDictionary.InsertContents(contentsList);
}
public WeakDictionary(int concurrencyLevel, int capacity, IEqualityComparer strongKeyComparer)
{
_internalDictionary =
new InternalWeakDictionary(
concurrencyLevel,
capacity,
new KeyComparer(strongKeyComparer)
)
;
}
public bool ContainsKey(TStrongKey strongKey)
{ return _internalDictionary.ContainsKey( new StrongKey(strongKey) ); }
public bool TryGetValue(TStrongKey strongKey, out TValue value)
{ return _internalDictionary.TryGetValue(new StrongKey(strongKey), out value); }
public TValue this[TStrongKey strongKey]
{
get { return _internalDictionary.GetItem(new StrongKey(strongKey)); }
set { _internalDictionary.SetItem(new StrongKey(strongKey), value); }
}
public bool IsEmpty
{ get { return _internalDictionary.IsEmpty; } }
public TValue AddOrUpdate(TStrongKey strongKey, Func addValueFactory, Func updateValueFactory)
{
if (null == addValueFactory)
throw new ArgumentNullException("addValueFactory");
if (null == updateValueFactory)
throw new ArgumentNullException("updateValueFactory");
return
_internalDictionary.AddOrUpdate(
new StrongKey(strongKey),
hr => addValueFactory(hr._element),
(hr, v) => updateValueFactory(hr._element, v)
)
;
}
public TValue AddOrUpdate(TStrongKey strongKey, TValue addValue, Func updateValueFactory)
{
if (null == updateValueFactory)
throw new ArgumentNullException("updateValueFactory");
return
_internalDictionary.AddOrUpdate(
new StrongKey(strongKey),
addValue,
(hr, v) => updateValueFactory(hr._element, v)
)
;
}
public TValue GetOrAdd(TStrongKey strongKey, TValue value)
{ return _internalDictionary.GetOrAdd(new StrongKey(strongKey), value); }
public TValue GetOrAdd(TStrongKey strongKey, Func valueFactory)
{
if (null == valueFactory)
throw new ArgumentNullException("valueFactory");
return _internalDictionary.GetOrAdd(new StrongKey(strongKey), hr => valueFactory(hr._element));
}
public KeyValuePair[] ToArray()
{ return _internalDictionary.ToArray(); }
public bool TryAdd(TStrongKey strongKey, TValue value)
{ return _internalDictionary.TryAdd(new StrongKey(strongKey), value); }
public bool TryRemove(TStrongKey strongKey, out TValue value)
{ return _internalDictionary.TryRemove(new StrongKey(strongKey), out value); }
public bool TryUpdate(TStrongKey strongKey, TValue newValue, TValue comparisonValue)
{ return _internalDictionary.TryUpdate(new StrongKey(strongKey), newValue, comparisonValue); }
}
}