Add L4 predictor queue skeleton
This commit is contained in:
@@ -1,4 +1,11 @@
|
||||
using System;
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="L4.PredictorQueue"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -6,7 +13,97 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.Common.HighPerformance.Memory
|
||||
{
|
||||
public class L4
|
||||
public partial class L4
|
||||
{
|
||||
|
||||
private readonly IL4Predictor[] _ring = new IL4Predictor[256];
|
||||
private volatile int _consume;
|
||||
private volatile int _enter;
|
||||
private volatile int _predict;
|
||||
|
||||
private int _queue_sync;
|
||||
|
||||
internal void DropPredictor(
|
||||
IL4Predictor predictor
|
||||
)
|
||||
{
|
||||
if (predictor is null) {
|
||||
return;
|
||||
}
|
||||
SpinWait sp = new();
|
||||
while (Interlocked.CompareExchange(ref _queue_sync, 1, 0) != 0) {
|
||||
sp.SpinOnce();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
for (int i = _consume; i < _predict; i++)
|
||||
{
|
||||
byte idx = (byte)i;
|
||||
if (ReferenceEquals(predictor, _ring[idx]))
|
||||
{
|
||||
int end = _predict;
|
||||
for (int move = i; move < end - 1; move++)
|
||||
{
|
||||
_ring[(byte)move] = _ring[(byte)(move + 1)];
|
||||
}
|
||||
_ring[(byte)(end - 1)] = default!;
|
||||
_predict = end - 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Exchange(ref _queue_sync, 0);
|
||||
}
|
||||
}
|
||||
|
||||
internal void RegistPredictor(
|
||||
IL4Predictor predictor
|
||||
)
|
||||
{
|
||||
if (predictor is null) {
|
||||
return;
|
||||
}
|
||||
SpinWait sp = new();
|
||||
while (Interlocked.CompareExchange(ref _queue_sync, 1, 0) != 0) {
|
||||
sp.SpinOnce();
|
||||
}
|
||||
|
||||
WaitForSpare();
|
||||
|
||||
_consume++;
|
||||
|
||||
byte idx = (byte)_consume;
|
||||
_ring[idx] = predictor;
|
||||
}
|
||||
|
||||
private void WaitForSpare()
|
||||
{
|
||||
int spin_count = 0;
|
||||
|
||||
// wait until the queue has space
|
||||
while (_enter - _consume >= 256)
|
||||
{
|
||||
switch (spin_count)
|
||||
{
|
||||
case < 1024:
|
||||
spin_count++;
|
||||
break;
|
||||
case < 65536:
|
||||
spin_count++;
|
||||
Thread.SpinWait(1);
|
||||
break;
|
||||
default:
|
||||
Thread.Sleep(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user