fix: Fixes pooled timer detach (#1115)
- [X] Fixes timers not returning on detach
This commit is contained in:
parent
9c374861d9
commit
a4168dc219
7 changed files with 804 additions and 816 deletions
|
|
@ -17,144 +17,145 @@ using System;
|
|||
using Server.Diagnostics;
|
||||
using Server.Logging;
|
||||
|
||||
namespace Server
|
||||
namespace Server;
|
||||
|
||||
public partial class Timer
|
||||
{
|
||||
public partial class Timer
|
||||
protected internal static readonly ILogger logger = LogFactory.GetLogger(typeof(Timer));
|
||||
|
||||
public static void Configure()
|
||||
{
|
||||
protected internal static readonly ILogger logger = LogFactory.GetLogger(typeof(Timer));
|
||||
ConfigureTimerPool();
|
||||
}
|
||||
|
||||
public static void Configure()
|
||||
// We need to know what ring/slot we are in so we can be removed if we are "head" of the link list.
|
||||
private int _ring;
|
||||
private int _slot;
|
||||
private long _remaining;
|
||||
private Timer _nextTimer;
|
||||
private Timer _prevTimer;
|
||||
|
||||
public Timer(TimeSpan delay) => Init(delay, TimeSpan.Zero, 1);
|
||||
|
||||
public Timer(TimeSpan interval, int count) => Init(interval, interval, count);
|
||||
|
||||
public Timer(TimeSpan delay, TimeSpan interval, int count = 0) => Init(delay, interval, count);
|
||||
|
||||
protected void Init(TimeSpan delay, TimeSpan interval, int count)
|
||||
{
|
||||
Running = false;
|
||||
Delay = delay;
|
||||
Index = 0;
|
||||
Interval = interval;
|
||||
Count = count;
|
||||
_nextTimer = null;
|
||||
_prevTimer = null;
|
||||
Next = Core.Now + Delay;
|
||||
|
||||
var prof = GetProfile();
|
||||
|
||||
if (prof != null)
|
||||
{
|
||||
ConfigureTimerPool();
|
||||
prof.Created++;
|
||||
}
|
||||
}
|
||||
|
||||
// We need to know what ring/slot we are in so we can be removed if we are "head" of the link list.
|
||||
private int _ring;
|
||||
private int _slot;
|
||||
private long _remaining;
|
||||
private Timer _nextTimer;
|
||||
private Timer _prevTimer;
|
||||
protected int Version { get; set; } // Used to determine if a timer was altered and we should abandon it.
|
||||
|
||||
public Timer(TimeSpan delay) => Init(delay, TimeSpan.Zero, 1);
|
||||
public DateTime Next { get; private set; }
|
||||
public TimeSpan Delay { get; set; }
|
||||
public TimeSpan Interval { get; set; }
|
||||
public int Index { get; private set; }
|
||||
public int Count { get; private set; }
|
||||
public int RemainingCount => Count - Index;
|
||||
public bool Running { get; private set; }
|
||||
|
||||
public Timer(TimeSpan interval, int count) => Init(interval, interval, count);
|
||||
public TimerProfile GetProfile() => !Core.Profiling ? null : TimerProfile.Acquire(ToString() ?? "null");
|
||||
|
||||
public Timer(TimeSpan delay, TimeSpan interval, int count = 0) => Init(delay, interval, count);
|
||||
public override string ToString() => GetType().FullName;
|
||||
|
||||
protected void Init(TimeSpan delay, TimeSpan interval, int count)
|
||||
public Timer Start()
|
||||
{
|
||||
if (Running)
|
||||
{
|
||||
Running = false;
|
||||
Delay = delay;
|
||||
Index = 0;
|
||||
Interval = interval;
|
||||
Count = count;
|
||||
_nextTimer = null;
|
||||
_prevTimer = null;
|
||||
Next = Core.Now + Delay;
|
||||
|
||||
var prof = GetProfile();
|
||||
|
||||
if (prof != null)
|
||||
{
|
||||
prof.Created++;
|
||||
}
|
||||
}
|
||||
|
||||
protected int Version { get; set; } // Used to determine if a timer was altered and we should abandon it.
|
||||
|
||||
public DateTime Next { get; private set; }
|
||||
public TimeSpan Delay { get; set; }
|
||||
public TimeSpan Interval { get; set; }
|
||||
public int Index { get; private set; }
|
||||
public int Count { get; private set; }
|
||||
public int RemainingCount => Count - Index;
|
||||
public bool Running { get; private set; }
|
||||
|
||||
public TimerProfile GetProfile() => !Core.Profiling ? null : TimerProfile.Acquire(ToString() ?? "null");
|
||||
|
||||
public override string ToString() => GetType().FullName;
|
||||
|
||||
public Timer Start()
|
||||
{
|
||||
if (Running)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
Index = 0;
|
||||
Running = true;
|
||||
AddTimer(this, (long)Delay.TotalMilliseconds);
|
||||
|
||||
var prof = GetProfile();
|
||||
|
||||
if (prof != null)
|
||||
{
|
||||
prof.Started++;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual void Stop()
|
||||
Index = 0;
|
||||
Running = true;
|
||||
AddTimer(this, (long)Delay.TotalMilliseconds);
|
||||
|
||||
var prof = GetProfile();
|
||||
|
||||
if (prof != null)
|
||||
{
|
||||
if (!Running)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not detach if we are in the middle of executing the timer wheel for this ring/slot
|
||||
if (!_timerWheelExecuting || _ringIndexes[_ring] != _slot)
|
||||
{
|
||||
// We are at the head
|
||||
if (_rings[_ring][_slot] == this)
|
||||
{
|
||||
_rings[_ring][_slot] = _nextTimer;
|
||||
}
|
||||
|
||||
Detach();
|
||||
}
|
||||
|
||||
Running = false;
|
||||
Version++;
|
||||
|
||||
var prof = GetProfile();
|
||||
if (prof != null)
|
||||
{
|
||||
prof.Stopped++;
|
||||
}
|
||||
prof.Started++;
|
||||
}
|
||||
|
||||
protected virtual void OnTick()
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (!Running)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
private void Attach(Timer timer)
|
||||
Running = false;
|
||||
|
||||
// Do not detach if we are in the middle of executing the timer wheel for this ring/slot
|
||||
if (!_timerWheelExecuting || _ringIndexes[_ring] != _slot)
|
||||
{
|
||||
_nextTimer = timer;
|
||||
if (timer != null)
|
||||
// We are at the head
|
||||
if (_rings[_ring][_slot] == this)
|
||||
{
|
||||
timer._prevTimer = this;
|
||||
_rings[_ring][_slot] = _nextTimer;
|
||||
}
|
||||
|
||||
Detach();
|
||||
OnDetach();
|
||||
}
|
||||
|
||||
private void Detach()
|
||||
{
|
||||
if (_prevTimer != null)
|
||||
{
|
||||
_prevTimer._nextTimer = _nextTimer;
|
||||
}
|
||||
|
||||
if (_nextTimer != null)
|
||||
{
|
||||
_nextTimer._prevTimer = _prevTimer;
|
||||
}
|
||||
|
||||
_nextTimer = null;
|
||||
_prevTimer = null;
|
||||
}
|
||||
|
||||
internal virtual void OnDetach()
|
||||
Version++;
|
||||
|
||||
var prof = GetProfile();
|
||||
if (prof != null)
|
||||
{
|
||||
prof.Stopped++;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnTick()
|
||||
{
|
||||
}
|
||||
|
||||
private void Attach(Timer timer)
|
||||
{
|
||||
_nextTimer = timer;
|
||||
if (timer != null)
|
||||
{
|
||||
timer._prevTimer = this;
|
||||
}
|
||||
}
|
||||
|
||||
private void Detach()
|
||||
{
|
||||
if (_prevTimer != null)
|
||||
{
|
||||
_prevTimer._nextTimer = _nextTimer;
|
||||
}
|
||||
|
||||
if (_nextTimer != null)
|
||||
{
|
||||
_nextTimer._prevTimer = _prevTimer;
|
||||
}
|
||||
|
||||
_nextTimer = null;
|
||||
_prevTimer = null;
|
||||
}
|
||||
|
||||
internal virtual void OnDetach()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue