v10.10.2024.0701 使用IJsonHost改进Json序列化
大石头 编写于 2024-07-01 08:36:34 大石头 提交于 2024-07-01 08:48:33
X
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;

namespace System.Collections.Concurrent;

[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(typeof(CollectionDebuggerView<>))]
public class ConcurrentStack<T> : IProducerConsumerCollection<T>, IEnumerable<T>, ICollection, IEnumerable
{
	private class Node
	{
		public T Value = default(T);

		public Node Next;
	}

	private class NodeObjectPool : ObjectPool<Node>
	{
		protected override Node Creator()
		{
			return new Node();
		}
	}

	private Node head;

	private int count;

	private static readonly NodeObjectPool pool = new NodeObjectPool();

	private object syncRoot = new object();

	bool ICollection.IsSynchronized => true;

	object ICollection.SyncRoot => syncRoot;

	public int Count => count;

	public bool IsEmpty => count == 0;

	private static Node ZeroOut(Node node)
	{
		node.Value = default(T);
		node.Next = null;
		return node;
	}

	public ConcurrentStack()
	{
	}

	public ConcurrentStack(IEnumerable<T> collection)
	{
		foreach (T item in collection)
		{
			Push(item);
		}
	}

	bool IProducerConsumerCollection<T>.TryAdd(T elem)
	{
		Push(elem);
		return true;
	}

	public void Push(T item)
	{
		Node node = pool.Take();
		node.Value = item;
		do
		{
			node.Next = head;
		}
		while (Interlocked.CompareExchange(ref head, node, node.Next) != node.Next);
		Interlocked.Increment(ref count);
	}

	public void PushRange(T[] items)
	{
		PushRange(items, 0, items.Length);
	}

	public void PushRange(T[] items, int startIndex, int count)
	{
		Node node = null;
		Node node2 = null;
		for (int i = startIndex; i < count; i++)
		{
			Node node3 = pool.Take();
			node3.Value = items[i];
			node3.Next = node;
			node = node3;
			if (node2 == null)
			{
				node2 = node3;
			}
		}
		do
		{
			node2.Next = head;
		}
		while (Interlocked.CompareExchange(ref head, node, node2.Next) != node2.Next);
		Interlocked.Add(ref count, count);
	}

	public bool TryPop(out T result)
	{
		Node node;
		do
		{
			node = head;
			if (node == null)
			{
				result = default(T);
				return false;
			}
		}
		while (Interlocked.CompareExchange(ref head, node.Next, node) != node);
		Interlocked.Decrement(ref count);
		result = node.Value;
		pool.Release(ZeroOut(node));
		return true;
	}

	public int TryPopRange(T[] items)
	{
		return TryPopRange(items, 0, items.Length);
	}

	public int TryPopRange(T[] items, int startIndex, int count)
	{
		Node next;
		Node node;
		do
		{
			next = head;
			if (next == null)
			{
				return -1;
			}
			node = next;
			for (int i = 0; i < count - 1; i++)
			{
				node = node.Next;
				if (node == null)
				{
					break;
				}
			}
		}
		while (Interlocked.CompareExchange(ref head, node, next) != next);
		int j;
		for (j = startIndex; j < count; j++)
		{
			if (next == null)
			{
				break;
			}
			items[j] = next.Value;
			node = next;
			next = next.Next;
			pool.Release(ZeroOut(node));
		}
		return j - 1;
	}

	public bool TryPeek(out T result)
	{
		Node node = head;
		if (node == null)
		{
			result = default(T);
			return false;
		}
		result = node.Value;
		return true;
	}

	public void Clear()
	{
		count = 0;
		head = null;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return InternalGetEnumerator();
	}

	public IEnumerator<T> GetEnumerator()
	{
		return InternalGetEnumerator();
	}

	private IEnumerator<T> InternalGetEnumerator()
	{
		Node my_head = head;
		if (my_head != null)
		{
			Node next;
			do
			{
				yield return my_head.Value;
				my_head = (next = my_head.Next);
			}
			while (next != null);
		}
	}

	void ICollection.CopyTo(Array array, int index)
	{
		if (array is T[] array2)
		{
			CopyTo(array2, index);
		}
	}

	public void CopyTo(T[] array, int index)
	{
		IEnumerator<T> enumerator = InternalGetEnumerator();
		int num = index;
		while (enumerator.MoveNext())
		{
			array[num++] = enumerator.Current;
		}
	}

	bool IProducerConsumerCollection<T>.TryTake(out T item)
	{
		return TryPop(out item);
	}

	public T[] ToArray()
	{
		T[] array = new T[count];
		CopyTo(array, 0);
		return array;
	}
}