public byte[] Read(int size)
{
if (size == 0 || isDisposing)
return new byte[0];
int spare = 0;
byte[] result = new byte[size];
long realLength = 0;
//if the readposition and the write osition is at the same position do
//wait for new data
dataSemaphore.WaitOne();
if (writePosition == readPosition)
{
dataSemaphore.Release();
waitForNewData.WaitOne();
}
else
dataSemaphore.Release();
//be sure we have enough data
do
{
if (isDisposing)
return new byte[0];
dataSemaphore.WaitOne();
if (writePosition < readPosition)
realLength = (data.Length - readPosition) + writePosition;
else
realLength = (writePosition - readPosition);
dataSemaphore.Release();
//if there is not enough data to read, it will wait till new arrives or
// one second passed. because it could be, that due to some really bad luck
// the new data just happened between the lock open and the wait.
if (size > realLength)
waitForNewData.WaitOne();
}
while (size > realLength);
if (isDisposing)
return new byte[0];
dataSemaphore.WaitOne();
//they are on the same loop
if (writePosition > readPosition)
{
Buffer.BlockCopy(data, readPosition, result, 0, size);
readPosition += size;
}
else
{
if ((data.Length - readPosition) >= size)
{
Buffer.BlockCopy(data, readPosition, result, 0, size);
readPosition += size;
}
else
{
spare = (data.Length - readPosition);
Buffer.BlockCopy(data, readPosition, result, 0, spare);
Buffer.BlockCopy(data, 0, result, spare, (size - spare));
readPosition = (size - spare);
}
}
dataSemaphore.Release();
waitForRead.Set();
return result;
}