File: CircularBuffer.cs
Web Access
Project: src\src\Libraries\Microsoft.Extensions.Diagnostics.ResourceMonitoring\Microsoft.Extensions.Diagnostics.ResourceMonitoring.csproj (Microsoft.Extensions.Diagnostics.ResourceMonitoring)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Microsoft.Shared.Diagnostics;
 
namespace Microsoft.Extensions.Diagnostics.ResourceMonitoring;
 
internal sealed class CircularBuffer<T>
{
    private const int BufferSizeMultiplier = 2;
    private readonly T[] _elements;
    private readonly int _maxDistance;
    private int _bufferCursor;
 
    public CircularBuffer(int size, T defaultElement)
    {
        _ = Throw.IfLessThan(size, 1);
 
        _elements = new T[size * BufferSizeMultiplier];
 
        _maxDistance = size;
 
        for (var i = 0; i < _elements.Length; i++)
        {
            _elements[i] = defaultElement;
        }
    }
 
    public (T firstElement, T lastElement) GetFirstAndLastFromWindow(int distance)
    {
        if (distance > _maxDistance)
        {
            distance = _maxDistance;
        }
 
        var lastElementCursor = _bufferCursor;
        var firstElementCursor = lastElementCursor - distance + 1;
        if (firstElementCursor < 0)
        {
            firstElementCursor += _elements.Length;
        }
 
        return (_elements[firstElementCursor], _elements[lastElementCursor]);
    }
 
    public void Add(T newElement)
    {
        var cursor = (_bufferCursor + 1) % _elements.Length;
        _elements[cursor] = newElement;
        _bufferCursor = cursor;
    }
}