Skip to content

Instantly share code, notes, and snippets.

@dranger003
Last active September 9, 2015 20:02
Show Gist options
  • Save dranger003/cb123f8c0570f293e23c to your computer and use it in GitHub Desktop.
Save dranger003/cb123f8c0570f293e23c to your computer and use it in GitHub Desktop.
using System;
using System.Threading;
namespace FORMATIQUE
{
public class BlockingQueue<T>
{
private int _head = -1;
private int _tail = -1;
private T[] _buffer;
private object _sync = new object();
public BlockingQueue(int capacity)
{
_buffer = new T[capacity];
}
public T[] Array { get { return _buffer; } }
public int Capacity { get { return _buffer.Length; } }
public int Length
{
get
{
lock (_sync)
{
if (IsEmpty)
return 0;
if (IsFull)
return _buffer.Length;
return (_tail - _head + _buffer.Length) % _buffer.Length;
}
}
}
public int Available
{
get
{
lock (_sync)
{
return _buffer.Length - Length;
}
}
}
public bool IsEmpty
{
get
{
lock (_sync)
{
return _head == -1 || _tail == -1;
}
}
}
public bool IsFull
{
get
{
lock (_sync)
{
return !IsEmpty && (_head == _tail || (_head == 0 && _tail == _buffer.Length));
}
}
}
public int Push(ArraySegment<T> data)
{
lock (_sync)
{
while (Available <= 0)
Monitor.Wait(_sync);
var size = Math.Min(data.Count, Available);
_ToggleEmptyFull();
var seg1 = new ArraySegment<T>(data.Array, data.Offset, Math.Min(size, _buffer.Length - _tail));
if (seg1.Count > 0)
{
((IList<T>)seg1).CopyTo(_buffer, _tail);
_tail += seg1.Count;
}
if (seg1.Count < size)
{
var seg2 = new ArraySegment<T>(data.Array, data.Offset + seg1.Count, size - seg1.Count);
((IList<T>)seg2).CopyTo(_buffer, 0);
_tail = seg2.Count;
}
Monitor.Pulse(_sync);
return size;
}
}
public int Pop(ArraySegment<T> data)
{
lock (_sync)
{
while (Length <= 0)
Monitor.Wait(_sync);
var size = Math.Min(data.Count, Length);
var seg1 = new ArraySegment<T>(_buffer, _head, Math.Min(size, _buffer.Length - _head));
if (seg1.Count > 0)
{
((IList<T>)seg1).CopyTo(data.Array, data.Offset);
_head += seg1.Count;
}
if (seg1.Count < size)
{
var seg2 = new ArraySegment<T>(_buffer, 0, size - seg1.Count);
((IList<T>)seg2).CopyTo(data.Array, data.Offset + seg1.Count);
_head = seg2.Count;
}
_ToggleEmptyFull();
Monitor.Pulse(_sync);
return size;
}
}
private void _ToggleEmptyFull()
{
if (_head == -1 || _tail == -1)
_head = _tail = 0;
else if (_head == _tail)
_head = _tail = -1;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment