using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using NewLife;
using NewLife.Collections;
using NewLife.Threading;
#if !NET4
namespace System.Collections.Concurrent
{
/// <summary>先进先出LIFO的原子栈结构,采用CAS保证线程安全。利用单链表实现。</summary>
/// <remarks>
/// 注意:<see cref="Push"/>、<see cref="TryPop"/>、<see cref="Pop"/>、<see cref="TryPeek"/>、<see cref="Peek"/>是重量级线程安全代码,不要随意更改。
///
/// 增加自由节点链表,避免频繁分配节点带来的GC压力。
///
/// 经过测试,对象数量在万级以上时,性能急剧下降!
/// </remarks>
/// <typeparam name="T"></typeparam>
[Serializable]
[DebuggerDisplay("Count = {Count}")]
public class ConcurrentStack<T> : DisposeBase, IStack<T>, IEnumerable<T>, ICollection, IEnumerable
{
#region 属性
/// <summary>栈顶</summary>
private SingleListNode<T> Top;
private Int32 _Count;
/// <summary>元素个数</summary>
public Int32 Count { get { return _Count; } }
/// <summary>是否空</summary>
public Boolean IsEmpty { get { return Top == null; } }
private Boolean _UseNodePool;
/// <summary>是否使用节点池。采用节点池可以避免分配节点造成的GC压力,但是会让性能有所降低。</summary>
public Boolean UseNodePool { get { return _UseNodePool; } set { _UseNodePool = value; } }
#endregion
#region 构造
/// <summary>实例化</summary>
public ConcurrentStack() { }
/// <summary>使用一个集合初始化</summary>
/// <param name="collection"></param>
public ConcurrentStack(IEnumerable<T> collection)
{
SingleListNode<T> node = null;
foreach (T local in collection)
{
var node2 = new SingleListNode<T>(local);
node2.Next = node;
node = node2;
}
Top = node;
}
/// <summary>子类重载实现资源释放逻辑时必须首先调用基类方法</summary>
/// <param name="disposing">从Dispose调用(释放所有资源)还是析构函数调用(释放非托管资源)</param>
protected override void OnDispose(bool disposing)
{
base.OnDispose(disposing);
Clear();
Top = null;
}
#endregion
#region 核心方法
/// <summary>向栈压入一个对象</summary>
/// <remarks>重点解决多线程环境下资源争夺以及使用lock造成性能损失的问题</remarks>
/// <param name="item"></param>
public void Push(T item)
{
Debug.Assert(item != null);
var node = CreateNode(item);
// 设置新对象的下一个节点为当前栈顶
node.Next = Top;
if (Interlocked.CompareExchange(ref Top, node, node.Next) != node.Next) this.PushCore(node, node);
Interlocked.Increment(ref _Count);
// 数量较多时,自动采用节点池
if (!UseNodePool && _Count > 100) UseNodePool = true;
}
/// <summary>向栈压入一个对象数组</summary>
/// <param name="items"></param>
/// <param name="startIndex"></param>
/// <param name="count"></param>
public void PushRange(T[] items, int startIndex = 0, int count = -1)
{
if (items == null) throw new ArgumentNullException("items");
if (count < 0) count = items.Length - startIndex;
if (count == 0) return;
var head = CreateNode(items[startIndex]);
var tail = head;
for (int i = startIndex + 1; i < startIndex + count; i++)
{
var node = CreateNode(items[i]);
node.Next = head;
head = node;
}
tail.Next = Top;
if (Interlocked.CompareExchange(ref Top, head, tail.Next) != tail.Next) this.PushCore(head, tail);
Interlocked.Add(ref _Count, count);
// 数量较多时,自动采用节点池
if (!UseNodePool && _Count > 100) UseNodePool = true;
}
private void PushCore(SingleListNode<T> head, SingleListNode<T> tail)
{
var wait = new SpinWait();
do
{
wait.SpinOnce();
// 设置新对象的下一个节点为当前栈顶
tail.Next = Top;
}
// 比较并交换
// 如果当前栈顶第一个参数的Top等于第三个参数,表明没有被别的线程修改,保存第二参数到第一参数中
// 否则,不相等表明当前栈顶已经被修改过,操作失败,执行循环
while (Interlocked.CompareExchange(ref Top, head, tail.Next) != tail.Next);
}
/// <summary>从栈中弹出一个对象</summary>
/// <returns></returns>
public T Pop()
{
T item;
if (!TryPop(out item)) throw new InvalidOperationException("栈为空!");
return item;
}
/// <summary>尝试从栈中弹出一个对象</summary>
/// <param name="item"></param>
/// <returns></returns>
public Boolean TryPop(out T item)
{
SingleListNode<T> newTop;
SingleListNode<T> oldTop;
//SpinWait sw = null;
while (true)
{
// 记住当前栈顶
oldTop = Top;
if (oldTop == null)
{
item = default(T);
return false;
}
Debug.Assert(_Count > 0);
// 设置新栈顶为当前栈顶的下一个节点
newTop = oldTop.Next;
// 比较并交换
// 如果当前栈顶第一个参数的Top等于第三个参数,表明没有被别的线程修改,保存第二参数到第一参数中
// 否则,不相等表明当前栈顶已经被修改过,操作失败,执行循环
if (Interlocked.CompareExchange(ref Top, newTop, oldTop) == oldTop) break;
Thread.SpinWait(1);
//if (sw == null) sw = new SpinWait();
//sw.SpinOnce();
}
Interlocked.Decrement(ref _Count);
item = oldTop.Item;
Debug.Assert(item != null);
if (UseNodePool)
PushNode(oldTop);
else
{
// 断开关系链,避免内存泄漏
oldTop.Next = null;
oldTop.Item = default(T);
}
return true;
}
/// <summary>获取栈顶对象,不弹栈</summary>
/// <returns></returns>
public T Peek()
{
T item;
if (!TryPeek(out item)) throw new InvalidOperationException("栈为空!");
return item;
}
/// <summary>尝试获取栈顶对象,不弹栈</summary>
/// <param name="item"></param>
/// <returns></returns>
public Boolean TryPeek(out T item)
{
var top = Top;
if (top == null)
{
item = default(T);
return false;
}
item = top.Item;
return true;
}
#endregion
#region 节点池
/// <summary>自由节点头部</summary>
private SingleListNode<T> FreeTop;
private Int32 FreeCount;
const Int32 MaxFreeCount = 100;
SingleListNode<T> CreateNode(T item) { return UseNodePool ? PopNode(item) : new SingleListNode<T>(item); }
SingleListNode<T> PopNode(T item)
{
SingleListNode<T> newTop;
SingleListNode<T> oldTop;
//SpinWait sw = null;
while (true)
{
// 记住当前栈顶
oldTop = FreeTop;
if (oldTop == null) return new SingleListNode<T>(item);
// 设置新栈顶为当前栈顶的下一个节点
newTop = oldTop.Next;
if (Interlocked.CompareExchange(ref FreeTop, newTop, oldTop) == oldTop) break;
Thread.SpinWait(1);
//if (sw == null) sw = new SpinWait();
//sw.SpinOnce();
}
Interlocked.Decrement(ref FreeCount);
oldTop.Next = null;
oldTop.Item = item;
return oldTop;
}
void PushNode(SingleListNode<T> node)
{
// 断开关系链,避免内存泄漏
node.Item = default(T);
//// 如果自由节点太多,就不要了
//if (FreeCount > MaxFreeCount) return;
var newTop = node;
//SpinWait sw = null;
while (true)
{
// 记住当前
var oldTop = FreeTop;
// 设置新对象的下一个节点为当前栈顶
newTop.Next = oldTop;
if (Interlocked.CompareExchange(ref FreeTop, newTop, oldTop) == oldTop) break;
Thread.SpinWait(1);
//if (sw == null) sw = new SpinWait();
//sw.SpinOnce();
}
Interlocked.Increment(ref FreeCount);
}
#endregion
#region 集合方法
/// <summary>清空</summary>
public void Clear()
{
var top = Top;
_Count = 0;
Top = null;
for (var node = top; node != null; node = node.Next)
{
if (UseNodePool)
PushNode(node);
else
{
// 断开关系链,避免内存泄漏
node.Next = null;
node.Item = default(T);
}
}
}
/// <summary>转为数组</summary>
/// <returns></returns>
public T[] ToArray() { return ToList().ToArray(); }
private List<T> ToList()
{
var list = new List<T>();
for (var node = Top; node != null; node = node.Next)
{
list.Add(node.Item);
}
return list;
}
#endregion
#region ICollection 成员
void ICollection.CopyTo(Array array, int index)
{
if (Top == null || array == null || index >= array.Length) return;
for (var node = Top; node != null && index < array.Length; node = node.Next) array.SetValue(node.Item, index++);
}
bool ICollection.IsSynchronized { get { return true; } }
private Object _syncRoot;
object ICollection.SyncRoot
{
get
{
if (_syncRoot == null)
{
Interlocked.CompareExchange(ref this._syncRoot, new object(), null);
}
return _syncRoot;
}
}
#endregion
#region IEnumerable 成员
/// <summary>获取枚举器</summary>
/// <returns></returns>
public IEnumerator<T> GetEnumerator()
{
for (var node = Top; node != null; node = node.Next) yield return node.Item;
}
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
#endregion
}
}
#endif
|