Last active
September 9, 2015 20:02
-
-
Save dranger003/cb123f8c0570f293e23c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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