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 } /// /// Notifies the taking thread that adding was stopped and must continue /// 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 } }