mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 12:30:32 +00:00
256 lines
9.4 KiB
C#
256 lines
9.4 KiB
C#
/*
|
|
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.Concurrent;
|
|
|
|
namespace Orvid.Concurrent.Collections
|
|
{
|
|
internal abstract class InternalWeakDictionaryStrongValueBase<IK, EK, EV, SK> : System.Collections.Concurrent.ConcurrentDictionary<IK, EV>, IMaintainable, IDictionary<EK, EV>, ICollection<KeyValuePair<EK, EV>>, IEnumerable<KeyValuePair<EK, EV>>
|
|
where IK : ITrashable
|
|
where SK : struct
|
|
{
|
|
protected InternalWeakDictionaryStrongValueBase(int concurrencyLevel, int capacity, IEqualityComparer<IK> keyComparer)
|
|
: base(concurrencyLevel, capacity, keyComparer)
|
|
{ }
|
|
|
|
protected InternalWeakDictionaryStrongValueBase(IEqualityComparer<IK> keyComparer)
|
|
: base(keyComparer)
|
|
{ }
|
|
|
|
protected abstract IK FromExternalKeyToSearchKey(EK externalKey);
|
|
protected abstract IK FromExternalKeyToStorageKey(EK externalKey);
|
|
protected abstract IK FromStackKeyToSearchKey(SK externalKey);
|
|
protected abstract IK FromStackKeyToStorageKey(SK externalKey);
|
|
protected abstract bool FromInternalKeyToExternalKey(IK internalKey, out EK externalKey);
|
|
protected abstract bool FromInternalKeyToStackKey(IK internalKey, out SK externalKey);
|
|
|
|
#region IMaintainable Members
|
|
|
|
void IMaintainable.DoMaintenance()
|
|
{
|
|
foreach (var kvp in (IEnumerable<KeyValuePair<IK, EV>>)this)
|
|
if (kvp.Key.IsGarbage)
|
|
{
|
|
EV value;
|
|
base.TryRemove(kvp.Key, out value);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IDictionary<Tuple<TWeakKey1,TStrongKey>,TValue> Members
|
|
|
|
void IDictionary<EK, EV>.Add(EK key, EV value)
|
|
{ ((IDictionary<IK, EV>)this).Add(FromExternalKeyToStorageKey(key), value); }
|
|
|
|
bool IDictionary<EK, EV>.ContainsKey(EK key)
|
|
{ return ((IDictionary<IK, EV>)this).ContainsKey(FromExternalKeyToSearchKey(key)); }
|
|
|
|
ICollection<EK> IDictionary<EK, EV>.Keys
|
|
{ get { return new TransformedCollection<EK> { _source = ((IEnumerable<KeyValuePair<EK, EV>>)this).Select(kvp => kvp.Key) }; } }
|
|
|
|
bool IDictionary<EK, EV>.Remove(EK key)
|
|
{ return ((IDictionary<IK, EV>)this).Remove(FromExternalKeyToSearchKey(key)); }
|
|
|
|
bool IDictionary<EK, EV>.TryGetValue(EK key, out EV value)
|
|
{ return base.TryGetValue(FromExternalKeyToSearchKey(key), out value); }
|
|
|
|
ICollection<EV> IDictionary<EK, EV>.Values
|
|
{ get { return new TransformedCollection<EV> { _source = ((IEnumerable<KeyValuePair<EK, EV>>)this).Select(kvp => kvp.Value) }; } }
|
|
|
|
EV IDictionary<EK, EV>.this[EK key]
|
|
{
|
|
get { return ((IDictionary<IK, EV>)this)[FromExternalKeyToSearchKey(key)]; }
|
|
set { ((IDictionary<IK, EV>)this)[FromExternalKeyToStorageKey(key)] = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ICollection<KeyValuePair<Tuple<TWeakKey1,TStrongKey>,TValue>> Members
|
|
|
|
void ICollection<KeyValuePair<EK, EV>>.Add(KeyValuePair<EK, EV> item)
|
|
{ ((IDictionary<EK, EV>)this).Add(item.Key, item.Value); }
|
|
|
|
void ICollection<KeyValuePair<EK, EV>>.Clear()
|
|
{ base.Clear(); }
|
|
|
|
bool ICollection<KeyValuePair<EK, EV>>.Contains(KeyValuePair<EK, EV> item)
|
|
{ return ((IDictionary<IK, EV>)this).Contains(new KeyValuePair<IK, EV>(FromExternalKeyToSearchKey(item.Key), item.Value)); }
|
|
|
|
//HIERO:
|
|
|
|
void ICollection<KeyValuePair<EK, EV>>.CopyTo(KeyValuePair<EK, EV>[] array, int arrayIndex)
|
|
{
|
|
if (array == null)
|
|
throw new ArgumentNullException("array");
|
|
|
|
if (arrayIndex < 0 || arrayIndex > array.Length)
|
|
throw new IndexOutOfRangeException();
|
|
|
|
int i = 0;
|
|
int end = array.Length - arrayIndex;
|
|
var buffer = new KeyValuePair<EK, EV>[end];
|
|
|
|
using (var it = ((IEnumerable<KeyValuePair<EK, EV>>)this).GetEnumerator())
|
|
while (it.MoveNext())
|
|
{
|
|
if (i == end)
|
|
throw new ArgumentException();
|
|
|
|
buffer[i++] = it.Current;
|
|
}
|
|
|
|
buffer.CopyTo(array, arrayIndex);
|
|
}
|
|
|
|
int ICollection<KeyValuePair<EK, EV>>.Count
|
|
{
|
|
get
|
|
{
|
|
int ct = 0;
|
|
|
|
using (var it = ((IEnumerable<KeyValuePair<EK, EV>>)this).GetEnumerator())
|
|
while (it.MoveNext())
|
|
++ct;
|
|
|
|
return ct;
|
|
}
|
|
}
|
|
|
|
bool ICollection<KeyValuePair<EK, EV>>.IsReadOnly
|
|
{ get { return false; } }
|
|
|
|
bool ICollection<KeyValuePair<EK, EV>>.Remove(KeyValuePair<EK, EV> item)
|
|
{ return RemoveIKVP(FromExternalKeyToSearchKey(item.Key), item.Value) ; }
|
|
|
|
#endregion
|
|
|
|
#region IEnumerable<KeyValuePair<EK, EV>> Members
|
|
|
|
public new IEnumerator<KeyValuePair<EK, EV>> GetEnumerator()
|
|
{
|
|
foreach (var kvp in (IEnumerable<KeyValuePair<IK, EV>>)this)
|
|
{
|
|
EK externalKey;
|
|
|
|
if (
|
|
FromInternalKeyToExternalKey(kvp.Key, out externalKey)
|
|
)
|
|
yield return new KeyValuePair<EK, EV>(externalKey, kvp.Value);
|
|
else
|
|
//boyscout
|
|
((ICollection<KeyValuePair<IK, EV>>)this).Remove(kvp);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
public bool ContainsKey(SK key)
|
|
{ return ((IDictionary<IK, EV>)this).ContainsKey(FromStackKeyToSearchKey(key)); }
|
|
|
|
public bool TryGetValue(SK key, out EV value)
|
|
{ return ((IDictionary<IK, EV>)this).TryGetValue(FromStackKeyToSearchKey(key), out value); }
|
|
|
|
public EV GetItem(SK key)
|
|
{ return ((IDictionary<IK, EV>)this)[FromStackKeyToStorageKey(key)]; }
|
|
|
|
public void SetItem(SK key, EV value)
|
|
{ ((IDictionary<IK, EV>)this)[FromStackKeyToStorageKey(key)] = value; }
|
|
|
|
public new bool IsEmpty
|
|
{ get { return !((ICollection<KeyValuePair<EK, EV>>)this).GetEnumerator().MoveNext(); } }
|
|
|
|
public EV AddOrUpdate(SK key, Func<SK, EV> addValueFactory, Func<SK, EV, EV> updateValueFactory)
|
|
{
|
|
return
|
|
base.AddOrUpdate(
|
|
FromStackKeyToStorageKey(key),
|
|
sKey => addValueFactory(key),
|
|
(sKey, oldValue) =>
|
|
{
|
|
SK oldKey;
|
|
|
|
if (FromInternalKeyToStackKey(sKey, out oldKey))
|
|
return updateValueFactory(oldKey, oldValue);
|
|
else
|
|
{
|
|
//boyscout
|
|
RemoveIKVP(sKey, oldValue);
|
|
return addValueFactory(key);
|
|
}
|
|
}
|
|
)
|
|
;
|
|
}
|
|
|
|
private bool RemoveIKVP(IK sKey, EV oldValue)
|
|
{
|
|
return ((ICollection<KeyValuePair<IK, EV>>)this).Remove(new KeyValuePair<IK, EV>(sKey, oldValue));
|
|
}
|
|
|
|
public EV AddOrUpdate(SK key, EV addValue, Func<SK, EV, EV> updateValueFactory)
|
|
{
|
|
return
|
|
AddOrUpdate(
|
|
FromStackKeyToStorageKey(key),
|
|
addValue,
|
|
(sKey, oldValue) =>
|
|
{
|
|
SK oldKey;
|
|
|
|
if (FromInternalKeyToStackKey(sKey, out oldKey))
|
|
return updateValueFactory(oldKey, oldValue);
|
|
else
|
|
{
|
|
//boyscout
|
|
RemoveIKVP(sKey, oldValue);
|
|
return addValue;
|
|
}
|
|
}
|
|
)
|
|
;
|
|
}
|
|
|
|
public EV GetOrAdd(SK key, EV value)
|
|
{ return base.GetOrAdd(FromStackKeyToStorageKey(key), value); }
|
|
|
|
public EV GetOrAdd(SK key, Func<SK, EV> valueFactory)
|
|
{
|
|
EV hold;
|
|
return this.TryGetValue(key, out hold) ? hold : GetOrAdd(key, valueFactory(key));
|
|
}
|
|
|
|
public new KeyValuePair<EK, EV>[] ToArray()
|
|
{ return ((IEnumerable<KeyValuePair<EK, EV>>)this).ToArray(); }
|
|
|
|
public bool TryAdd(SK key, EV value)
|
|
{ return base.TryAdd(FromStackKeyToStorageKey(key), value); }
|
|
|
|
public bool TryRemove(SK key, out EV value)
|
|
{ return base.TryRemove(FromStackKeyToSearchKey(key), out value); }
|
|
|
|
public bool TryUpdate(SK key, EV newValue, EV comparisonValue)
|
|
{ return base.TryUpdate(FromStackKeyToSearchKey(key), newValue, comparisonValue); }
|
|
|
|
public List<KeyValuePair<EK, EV>> GetContents()
|
|
{ return ((IEnumerable<KeyValuePair<EK, EV>>)this).ToList(); }
|
|
|
|
public void InsertContents(IEnumerable<KeyValuePair<EK, EV>> collection)
|
|
{
|
|
if (null == collection)
|
|
throw new ArgumentNullException("collection");
|
|
|
|
foreach (var kvp in collection)
|
|
((IDictionary<EK, EV>)this).Add(kvp);
|
|
}
|
|
}
|
|
}
|