CircularBufferBuckets
using System.Runtime.CompilerServices;
namespace System.Diagnostics.Metrics
{
internal sealed class CircularBufferBuckets
{
private long[] _trait;
private int _begin;
private int _end = -1;
public int Capacity { get; }
public int Size => _end - _begin + 1;
public long this[int index] {
get {
return _trait[ModuloIndex(index)];
}
}
public CircularBufferBuckets(int capacity)
{
if (capacity < 1)
throw new ArgumentOutOfRangeException("capacity", "Capacity must be greater than 0.");
Capacity = capacity;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int TryIncrement(int index, long value = 1)
{
int capacity = Capacity;
if (_trait == null) {
_trait = new long[capacity];
_begin = index;
_end = index;
_trait[ModuloIndex(index)] += value;
return 0;
}
int num = _begin;
int num2 = _end;
if (index > num2)
num2 = index;
else {
if (index >= num) {
_trait[ModuloIndex(index)] += value;
return 0;
}
num = index;
}
int num3 = num2 - num;
if (num3 >= capacity || num3 < 0)
return <TryIncrement>g__CalculateScaleReduction|11_0(num, num2, capacity);
_begin = num;
_end = num2;
_trait[ModuloIndex(index)] += value;
return 0;
}
public void ScaleDown(int level = 1)
{
if (_trait != null) {
uint capacity = (uint)Capacity;
uint num = (uint)ModuloIndex(_begin);
int num2 = _begin;
int num3 = _end;
for (int i = 0; i < level; i++) {
int num4 = num2 >> 1;
int num5 = num3 >> 1;
if (num2 != num3) {
if (num2 % 2 == 0)
<ScaleDown>g__ScaleDownInternal|12_0(_trait, num, num2, num3, capacity);
else {
num2++;
if (num2 != num3)
<ScaleDown>g__ScaleDownInternal|12_0(_trait, num + 1, num2, num3, capacity);
}
}
num2 = num4;
num3 = num5;
}
_begin = num2;
_end = num3;
if (capacity > 1)
<ScaleDown>g__AdjustPosition|12_1(_trait, num, (uint)ModuloIndex(num2), (uint)(num3 - num2 + 1), capacity);
}
}
public long[] ToArray()
{
int size = Size;
if (_trait == null || size <= 0)
return Array.Empty<long>();
long[] array = new long[size];
for (int i = 0; i < size; i++) {
array[i] = _trait[ModuloIndex(_begin + i)];
}
return array;
}
internal void Clear()
{
if (_trait != null)
Array.Clear(_trait, 0, _trait.Length);
_begin = 0;
_end = -1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int ModuloIndex(int value)
{
return PositiveModulo32(value, Capacity);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int PositiveModulo32(int value, int divisor)
{
value %= divisor;
if (value < 0)
value += divisor;
return value;
}
}
}