using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using Tools.Collections.Concurrent.Extensions;
namespace Tools.Collections.Concurrent
{
/// <summary>
/// Thread safe key value link-item collection.
/// Item remove if link count is 0.
/// Base on ConcurrentDictionary.
/// </summary>
public class LinkItemDictionary<TKey, TData>
{
#region
public IReadOnlyDictionary<TKey, IValueWrapper<LinkItem<TKey, TData>>> Storage { private set; get; }
private readonly ConcurrentDictionary<TKey, IValueWrapper<LinkItem<TKey, TData>>> _Storage
= new ConcurrentDictionary<TKey, IValueWrapper<LinkItem<TKey, TData>>>();
private readonly ICollection<KeyValuePair<TKey, IValueWrapper<LinkItem<TKey, TData>>>> _StorageAsCollection;
#endregion
#region
public LinkItemDictionary()
{
Storage = (IReadOnlyDictionary<TKey, IValueWrapper<LinkItem<TKey, TData>>>)_Storage;
_StorageAsCollection = _Storage;
}
#endregion
#region
/// <summary>
/// Add link. Add or update Value
/// </summary>
public LinkItem<TKey, TData> AddLink(
TKey key,
Func<TKey, TData> addFactory,
Func<LinkItem<TKey, TData>, TData> updateFactory
)
{
return _Storage.AddOrUpdate(
key,
(TKey k) =>
{
return
new RealItemWrapper<LinkItem<TKey, TData>>(
new LinkItem<TKey, TData>
(
key,
1,
addFactory != null ? addFactory(key) : default(TData)
)
);
},
(TKey k, IValueWrapper<LinkItem<TKey, TData>> old_value) =>
{
return
new RealItemWrapper<LinkItem<TKey, TData>>(
new LinkItem<TKey, TData>(
key,
old_value.Value.LinkCount + 1,
updateFactory != null
? updateFactory(old_value.Value)
: old_value.Value.Value
)
);
}
)
.Value;
}
/// <summary>
/// Add link. Add Value
/// </summary>
public LinkItem<TKey, TData> AddLink(
TKey key,
Func<TKey, TData> addFactory)
{
return AddLink(key, addFactory, null);
}
/// <summary>
/// Add link. Update value if exsist
/// </summary>
public LinkItem<TKey, TData> AddLink(
TKey key,
Func<LinkItem<TKey, TData>, TData> updateFactory)
{
return AddLink(key, null, updateFactory);
}
/// <summary>
/// Add link. No change value
/// </summary>
public LinkItem<TKey, TData> AddLink(
TKey key
)
{
return AddLink(key, null, null);
}
/// <summary>
/// Remove link. Update value
/// </summary>
public LinkItem<TKey, TData> RemoveLink(
TKey key,
Func<LinkItem<TKey, TData>, TData> updateFactory)
{
var item = _Storage.AddOrUpdate(
key,
(TKey k) =>
{
return
new RealItemWrapper<LinkItem<TKey, TData>>(
new LinkItem<TKey, TData>(
key,
0,
default(TData)
)
);
},
(TKey k, IValueWrapper<LinkItem<TKey, TData>> old_value) =>
{
return
new RealItemWrapper<LinkItem<TKey, TData>>(
new LinkItem<TKey, TData>(
key,
old_value.Value.LinkCount - 1,
updateFactory != null
? updateFactory(old_value.Value)
: old_value.Value.Value
)
);
}
);
if (item.Value.LinkCount == 0)
{
_StorageAsCollection.RemoveIf(
key,
(value) =>
{
return value.Value.LinkCount == 0;
}
);
}
return item.Value;
}
/// <summary>
/// Remove link. No change value if not remove
/// </summary>
public LinkItem<TKey, TData> RemoveLink(TKey key)
{
return RemoveLink(key, null);
}
#endregion
}
}