记录一下,等用到的时候直接copy, 不过这个不是线程安全的,如果需要多线程访问,需要加锁。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace test
{
public class QueueNoSpaceException : Exception
{ }
public class QueueEmptyException : Exception
{ }
public class StorageQueue<T>
{
private int _size = 0;
private T[] _buffer;
private int _head = 0;
private int _tail = 0;
private int _remainingSpace = 0;
public StorageQueue(int size)
{
if (size <= 0)
{
throw new ArgumentException("size is less or equal to zero");
}
_size = size + 1;
_buffer = new T[_size];
_head = _tail = 0;
_remainingSpace = _size - 1;
}
public bool IsEmpty
{
get
{
if (_head == _tail) // empty
return true;
else
return false;
}
}
public bool IsFull
{
get
{
if ((_tail + 1) % _size == _head)
{ return true; }
return false;
}
}
public int RemainingSpaces
{
get { return _remainingSpace; }
}
public void Enqueue(T item)
{
if (item == null)
{ throw new ArgumentNullException("item"); }
Enqueue(new T[1] { item });
}
public void Enqueue(T[] items)
{
if (items == null)
{ throw new ArgumentNullException("items"); }
Enqueue(items, 0, items.Length);
}
public void Enqueue(T[] items, int offset, int count)
{
if (items == null)
{ throw new ArgumentNullException("items"); }
if (offset < 0 || count <= 0 || items.Length < offset + count)
{ throw new ArgumentOutOfRangeException(); }
if (IsFull || _remainingSpace < count)
{ throw new QueueNoSpaceException(); }
lock (_buffer)
{
for (int i = 0; i < count; i++)
{
_buffer[_tail++] = items[offset + i];
_tail = (_tail) % _size;
}
_remainingSpace -= count;
}
}
public void Dequeue(out T item)
{
if (IsEmpty)
{ throw new QueueEmptyException(); }
item = _buffer[_head++];
_head = _head % _size;
_remainingSpace++;
}
public void DequeueBlocking(out T item)
{
if (IsEmpty)
{ throw new QueueEmptyException(); }
item = _buffer[_head++];
_head = _head % _size;
_remainingSpace++;
}
//dequeue "count" elements, return the dequeue number of elements
public int Dequeue(ref T[] arr, int offset, int count)
{
if (arr == null)
{ throw new ArgumentNullException("arr"); }
if (offset < 0 || count <= 0 || arr.Length < offset + count)
{ throw new ArgumentOutOfRangeException(); }
if (IsEmpty)
{ throw new QueueEmptyException(); }
int i = 0;
do
{
arr[offset + i] = _buffer[_head++];
i++;
_head = _head % _size;
} while (!IsEmpty && i < count);
_remainingSpace += i;
return i;
}
}
}
using System;
using System.Text;
using System.Collections.Generic;
using System.Net;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using test;
namespace UTPCService.connection
{
[TestClass]
public class StorageQueueTest
{
[TestInitialize]
public void Init()
{
_queue = new StorageQueue<byte>(_size);
}
private StorageQueue<byte> _queue;
private const int _size = 10;
[TestMethod]
[ExpectedException(typeof(QueueNoSpaceException))]
public void QueueFull_Test()
{
byte[] arr = new byte[_size + 1];
_queue.Enqueue(arr);
}
[TestMethod]
[ExpectedException(typeof(QueueEmptyException))]
public void QueueEmpty_Test()
{
byte b = 0;
_queue.Dequeue(out b);
}
[TestMethod]
public void Queue_Item_Test()
{
byte b = 123;
byte c = 0;
_queue.Enqueue(b);
_queue.Dequeue(out c);
Assert.AreEqual(b, c);
}
[TestMethod]
public void Queue_Array_Test()
{
byte[] b = { 123, 0, 126 };
byte[] c = new byte[10];
_queue.Enqueue(b);
_queue.Dequeue(ref c, 0, b.Length);
for (int i = 0; i < b.Length; i++)
{
Assert.AreEqual(b[i], c[i]);
}
}
[TestMethod]
public void Boundary_Test()
{
byte[] b = new byte[_size] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
_queue.Enqueue(b);
Assert.IsTrue(_queue.IsFull);
byte[] c = new byte[10];
_queue.Dequeue(ref c, 0, _size);
Assert.IsTrue(_queue.IsEmpty);
//change full position
_queue.Enqueue(b, 0, 3);
_queue.Dequeue(ref c, 0, 3);
Assert.IsTrue(_queue.IsEmpty);
_queue.Enqueue(b);
Assert.IsTrue(_queue.IsFull);
_queue.Dequeue(ref c, 0, _size);
Assert.IsTrue(_queue.IsEmpty);
}
}
}