SafeDispatch/SipComponent/VoiceBuffer2.cs
2024-02-22 18:43:59 +02:00

149 lines
4.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SipComponent
{
class VoiceBuffer2
{
ByteQueue _byteQueue;
int _maxSize;
object _lockerOnTake = new object();
object _lockerOnAdd = new object();
bool _addingWasStopped;
volatile bool _fireEventHalfFull = true;
public VoiceBuffer2(int maxSize)
{
_maxSize = maxSize;
_byteQueue = new ByteQueue();
}
/*
public int TakeBytes(byte[] b)
{
int nbObBytesTaken = 0;
int length = b.Length;
lock (_lockerOnTake)
{
while (_byteQueue.Length < length && !_addingWasStopped)
{
OnEmpty(new EventArgs());
Monitor.Wait(_lockerOnTake);
}
if (_addingWasStopped)
return nbObBytesTaken;
}
nbObBytesTaken = _byteQueue.Dequeue(b, 0, length);
// Notify that adding can unblock
lock (_lockerOnAdd)
Monitor.Pulse(_lockerOnAdd);
#if DEBUG
//Console.WriteLine(_byteQueue.Length);
#endif
return nbObBytesTaken;
}
*/
public int TakeBytes(byte[] b)
{
int nbObBytesTaken = 0;
int length = b.Length;
lock (_lockerOnTake)
{
while (_byteQueue.Length < length && !_addingWasStopped)
{
OnEmpty(new EventArgs());
Monitor.Wait(_lockerOnTake);
}
//if (_addingWasStopped)
// return nbObBytesTaken;
}
nbObBytesTaken = _byteQueue.Dequeue(b, 0, length);
// Notify that adding can unblock
lock (_lockerOnAdd)
Monitor.Pulse(_lockerOnAdd);
//#if DEBUG
// Console.WriteLine(_byteQueue.Length);
//#endif
return nbObBytesTaken;
}
public void AddBytes(byte[] b)
{
int length = b.Length;
lock (_lockerOnAdd)
{
if (_addingWasStopped)
throw new SipClassException("Cannot add bytes to VoiceBuffer after calling StopAdding() method!");
while (_byteQueue.Length + length > _maxSize)
{
OnFull(new EventArgs());
Monitor.Wait(_lockerOnAdd);
}
}
_byteQueue.Enqueue(b, 0, b.Length);
// Notify that taking thread can unblock
lock (_lockerOnTake)
{
Monitor.Pulse(_lockerOnTake);
}
if (_fireEventHalfFull)
{
if (_byteQueue.Length >= _maxSize / 2)
{
OnHalfFull(new EventArgs());
_fireEventHalfFull = false;
}
}
//#if DEBUG
// Console.WriteLine(_byteQueue.Length);
//#endif
}
/// <summary>
/// Notifies the taking thread that adding was stopped and must continue
/// </summary>
public void StopAdding()
{
lock (_lockerOnTake)
{
_addingWasStopped = true;
Monitor.PulseAll(_lockerOnTake);
}
}
#region Events
public event EventHandler HalfFull;
public event EventHandler Full;
public event EventHandler Empty;
public void OnHalfFull(EventArgs e)
{
EventHandler handler = HalfFull;
if (handler != null)
handler(this, e);
}
public void OnFull(EventArgs e)
{
EventHandler handler = Full;
if (handler != null)
handler(this, e);
}
public void OnEmpty(EventArgs e)
{
EventHandler handler = Empty;
if (handler != null)
handler(this, e);
}
#endregion
}
}