123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- 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.Now;
- 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.Now));
- }
- }
- 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);
- }
- }
- }
- }
- }
- }
- }
- }
|