Code Review Asked on October 27, 2021
I need to speed up a circular buffer that has space and time requirements.
Each cell in the circular buffer represents a list of N elements to be sent. The shipment takes place if the list reaches N elements, or if the elapsed time exceeds X ms.
At the moment I have found this solution, but I am quite sure it is not the best possible to achieve my goal. I would like to understand if there are improvements for architecture.
public class RingBuffer<T> : IDisposable
{
protected class TimerArray
{
private Timer _timer;
private Int32 _index;
private RingBuffer<T> _ring;
public TimerArray(RingBuffer<T> ring, Int32 index)
{
_index = index;
_ring = ring;
_timer = new Timer(t => { ring.Send(_index); }, null, ring.TimerPeriod, ring.TimerPeriod);
}
public Boolean TimerReset()
{
return _timer.Change(_ring.TimerPeriod, _ring.TimerPeriod);
}
}
protected Object _locker = new Object();
protected ConcurrentQueue<T>[] _buffers;
protected TimerArray[] _timer;
protected Int64 current = 0;
public Int32 RingDimension { get; set; }
public Int32 SendSize { get; set; }
public Int32 TimerPeriod { get; set; }
public ISender Sender { get; set; }
public Int64 BufferSize { get; set; }
public RingBuffer(ISender sender, Int32 size, Int32 msTimer)
{
RingDimension = 10;
Init(sender, size, msTimer);
}
public RingBuffer(ISender sender, Int32 dimension, Int32 size, Int32 msTimer)
{
RingDimension = dimension;
Init(sender, size, msTimer);
}
protected void Init(ISender sender, Int32 size, Int32 msTimer)
{
_buffers = new ConcurrentQueue<T>[RingDimension];
Sender = sender;
SendSize = size == 0 ? -1 : size;
TimerPeriod = msTimer;
for (int i = 0; i < RingDimension; i++)
_buffers[i] = new ConcurrentQueue<T>();
if (TimerPeriod > 0)
{
_timer = new TimerArray[RingDimension];
for (int i = 0; i < RingDimension; i++)
_timer[i] = new TimerArray(this, i);
}
}
public void Enqueue(T item)
{
lock (_locker)
{
if (!Object.ReferenceEquals(item, null))
_buffers[current].Enqueue(item);
}
if (_buffers[current].Count >= SendSize)
{
lock (_locker)
{
if (_buffers[current].Count >= SendSize)
{
var previous = Interlocked.Exchange(ref current, (current + 1) % RingDimension);
if (TimerPeriod > 0)
_timer[previous].TimerReset();
BufferSize += Sender.Enqueue(_buffers[previous].ToList());
_buffers[previous] = new ConcurrentQueue<T>();
}
}
}
}
protected void Send(Int64 index)
{
if (_buffers[index].Count > 0)
{
lock (_locker)
{
if (_buffers[index].Count > 0)
{
BufferSize += Sender.Enqueue(_buffers[index].ToList());
_buffers[index] = new ConcurrentQueue<T>();
}
}
}
}
public virtual void Dispose()
{
}
}
Enqueue method is called by program anytime that a message is ready, check the list dimension and send it when list is full.
Send method is called by a Timer array that set a boundry limit for message latency.
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP