add all
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
using Best.HTTP.Shared;
|
||||
using Best.HTTP.Shared.PlatformSupport.Threading;
|
||||
|
||||
namespace Best.HTTP.Shared.Extensions
|
||||
{
|
||||
public readonly struct TimerData
|
||||
{
|
||||
public readonly DateTime Created;
|
||||
public readonly TimeSpan Interval;
|
||||
public readonly object Context;
|
||||
|
||||
public readonly Func<DateTime, object, bool> OnTimer;
|
||||
|
||||
public bool IsOnTime(DateTime now)
|
||||
{
|
||||
return now >= this.Created + this.Interval;
|
||||
}
|
||||
|
||||
public TimerData(TimeSpan interval, object context, Func<DateTime, object, bool> onTimer)
|
||||
{
|
||||
this.Created = DateTime.UtcNow;
|
||||
this.Interval = interval;
|
||||
this.Context = context;
|
||||
this.OnTimer = onTimer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new TimerData but the Created field will be set to the current time.
|
||||
/// </summary>
|
||||
public TimerData CreateNew()
|
||||
{
|
||||
return new TimerData(this.Interval, this.Context, this.OnTimer);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[TimerData Created: {0}, Interval: {1}, IsOnTime: {2}]", this.Created.ToString(System.Globalization.CultureInfo.InvariantCulture), this.Interval, this.IsOnTime(DateTime.UtcNow));
|
||||
}
|
||||
}
|
||||
|
||||
public static class Timer
|
||||
{
|
||||
private static List<TimerData> _timers = new List<TimerData>(1);
|
||||
private static ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
|
||||
|
||||
private static int _isSubscribed;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
public static void ResetSetup()
|
||||
{
|
||||
HTTPManager.Logger.Information(nameof(Timer), "Reset called!");
|
||||
Interlocked.Exchange(ref _isSubscribed, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
public static void Add(TimerData timer)
|
||||
{
|
||||
using (var _ = new WriteLock(_lock))
|
||||
_timers.Add(timer);
|
||||
|
||||
if (Interlocked.CompareExchange(ref _isSubscribed, 1, 0) == 0)
|
||||
{
|
||||
HTTPManager.Logger.Information(nameof(Timer), "Subscribing timer to heartbeats!");
|
||||
HTTPManager.Heartbeats.Subscribe(new TimerImplementation());
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class TimerImplementation : IHeartbeat
|
||||
{
|
||||
public void OnHeartbeatUpdate(DateTime now, TimeSpan dif)
|
||||
{
|
||||
using var __ = new Unity.Profiling.ProfilerMarker(nameof(Timer)).Auto();
|
||||
|
||||
using (var _ = new WriteLock(_lock))
|
||||
{
|
||||
if (_timers.Count == 0)
|
||||
{
|
||||
HTTPManager.Heartbeats.Unsubscribe(this);
|
||||
|
||||
Interlocked.Exchange(ref _isSubscribed, 0);
|
||||
|
||||
HTTPManager.Logger.Information(nameof(Timer), "Unsubscribing timer from heartbeats!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _timers.Count; ++i)
|
||||
{
|
||||
TimerData timer = _timers[i];
|
||||
|
||||
if (timer.IsOnTime(now))
|
||||
{
|
||||
try
|
||||
{
|
||||
bool repeat = timer.OnTimer(now, timer.Context);
|
||||
|
||||
if (repeat)
|
||||
_timers[i] = timer.CreateNew();
|
||||
else
|
||||
_timers.RemoveAt(i--);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
HTTPManager.Logger.Exception(nameof(Timer), "OnTimer", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user