add cancellable time span await
This commit is contained in:
@@ -43,15 +43,16 @@ namespace StgSharp.HighPerformance
|
||||
public M64()
|
||||
{
|
||||
Unsafe.SkipInit(out this);
|
||||
value = 0;
|
||||
Unsafe.SkipInit(out vec);
|
||||
Unsafe.SkipInit(out value);
|
||||
}
|
||||
|
||||
public ref T AsRef<T>() where T: unmanaged,INumber<T>
|
||||
public ref T AsRef<T>() where T : unmanaged,INumber<T>
|
||||
{
|
||||
return ref Unsafe.As<byte, T>(ref buffer[0]);
|
||||
}
|
||||
|
||||
public void BroadCastFrom<T>(T value) where T: unmanaged, INumber<T>
|
||||
public void BroadCastFrom<T>(T value) where T : unmanaged, INumber<T>
|
||||
{
|
||||
vec = Vector64.Create(value).AsSingle();
|
||||
}
|
||||
@@ -67,7 +68,7 @@ namespace StgSharp.HighPerformance
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref T Member<T>(int index) where T: unmanaged, INumber<T>
|
||||
public ref T Member<T>(int index) where T : unmanaged, INumber<T>
|
||||
{
|
||||
return ref Unsafe.As<byte, T>(ref buffer[index * sizeof(T)]);
|
||||
}
|
||||
@@ -77,28 +78,10 @@ namespace StgSharp.HighPerformance
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static M64 operator <<(M64 m, int shift)
|
||||
{
|
||||
return new M64
|
||||
{
|
||||
value = m.value << shift
|
||||
};
|
||||
}
|
||||
|
||||
public static bool operator ==(M64 left, M64 right)
|
||||
{
|
||||
return left.value == right.value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static M64 operator >>(M64 m, int shift)
|
||||
{
|
||||
return new M64
|
||||
{
|
||||
value = m.value >> shift
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,12 @@ namespace StgSharp.Timing
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// mark provider as ended so external users can observe terminal state
|
||||
try
|
||||
{
|
||||
Volatile.Write(ref _endedFlag, 1);
|
||||
}
|
||||
catch { }
|
||||
s_unusedID.Push(TokenID);
|
||||
_event.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
@@ -147,6 +153,46 @@ namespace StgSharp.Timing
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wait for the next timespan tick, but honor the provided cancellation token. Throws
|
||||
/// OperationCanceledException when token is cancelled. If the provider is disposed during
|
||||
/// wait an OperationCanceledException is thrown to indicate end.
|
||||
/// </summary>
|
||||
public Task WaitNextSpanAsync(CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Block the current thread until the event is signaled or cancellation requested.
|
||||
_event.Wait(ct);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
// provider disposed while waiting - treat as cancellation/ended
|
||||
throw new OperationCanceledException(ct);
|
||||
}
|
||||
|
||||
// consume one pending span (same logic as non-cancellable variant)
|
||||
while (true)
|
||||
{
|
||||
int cur = Volatile.Read(ref _pendingSpans);
|
||||
if (cur == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (Interlocked.CompareExchange(ref _pendingSpans, cur - 1, cur) == cur)
|
||||
{
|
||||
if (cur - 1 == 0) {
|
||||
_event.Reset();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
internal void MissRefresh() => _missHandler?.Invoke(this, EventArgs.Empty); // Legacy compatibility.
|
||||
|
||||
/// <summary>
|
||||
@@ -163,13 +209,16 @@ namespace StgSharp.Timing
|
||||
{
|
||||
if (_sequence.EndsAt(currentTick))
|
||||
{
|
||||
// mark ended due to sequence timeout, then dispose
|
||||
Volatile.Write(ref _endedFlag, 1);
|
||||
Dispose();
|
||||
return false;
|
||||
}
|
||||
if (!_sequence.IsNextFrameReady(currentTick)) {
|
||||
return true;
|
||||
}
|
||||
Console.WriteLine("Frame hit!");
|
||||
|
||||
// Console.WriteLine("Frame hit!");
|
||||
|
||||
// Fast path: if no pending consumers, initialize the counter to current capacity (_size).
|
||||
if (Volatile.Read(ref _pendingSpans) == 0)
|
||||
|
||||
@@ -41,6 +41,9 @@ namespace StgSharp.Timing
|
||||
|
||||
private bool _subscribed;
|
||||
private int _emittedSpanCount; // legacy counter
|
||||
|
||||
// internal ended flag (0 = running, 1 = ended)
|
||||
private int _endedFlag = 0;
|
||||
private readonly TimeSequence _sequence;
|
||||
private readonly TimeSourceProviderBase _timeSource;
|
||||
|
||||
@@ -62,6 +65,11 @@ namespace StgSharp.Timing
|
||||
_pendingSpans = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True when the provider has reached its end and will not emit further spans.
|
||||
/// </summary>
|
||||
public bool IsEnded => Volatile.Read(ref _endedFlag) != 0;
|
||||
|
||||
public double CurrentSecond
|
||||
{
|
||||
get => (double)_sequence.PreviousFrameTick / _timeSource.Frequency;
|
||||
|
||||
Reference in New Issue
Block a user