Files
2025-09-18 17:55:52 -04:00

79 lines
2.5 KiB
C#

using System;
using System.Threading;
namespace Roblox.Common
{
public class NonReentrantTimer : MarshalByRefObject, IDisposable
{
private Timer _timer;
private TimerCallback _callback;
private TimerCallback _skipExecutionCallback;
private int _count;
private NonReentrantTimer(TimerCallback callback)
{
_callback = callback;
_count = 0;
_skipExecutionCallback = null;
}
public NonReentrantTimer(TimerCallback callback, object state, int dueTime, int period) : this(callback)
{
_timer = new Timer(InternalCallback, state, dueTime, period);
}
public NonReentrantTimer(TimerCallback callback, object state, long dueTime, long period)
: this(callback)
{
_timer = new Timer(InternalCallback, state, dueTime, period);
}
public NonReentrantTimer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period)
: this(callback)
{
_timer = new Timer(InternalCallback, state, dueTime, period);
}
public NonReentrantTimer(TimerCallback callback, object state, uint dueTime, uint period)
: this(callback)
{
_timer = new Timer(InternalCallback, state, dueTime, period);
}
public TimerCallback SkipExecutionCallback { get { return _skipExecutionCallback; } set { _skipExecutionCallback = value; } }
public bool Change(int dueTime, int period)
{
return _timer.Change(dueTime, period);
}
public bool Change(long dueTime, long period)
{
return _timer.Change(dueTime, period);
}
public bool Change(TimeSpan dueTime, TimeSpan period)
{
return _timer.Change(dueTime, period);
}
public bool Change(uint dueTime, uint period)
{
return _timer.Change(dueTime, period);
}
private void InternalCallback(object state)
{
try
{
if (Interlocked.Increment(ref _count) == 1) _callback(state);
else _skipExecutionCallback?.Invoke(state);
}
finally
{
Interlocked.Decrement(ref _count);
}
}
public bool Dispose(WaitHandle notifyObject)
{
return _timer != null && _timer.Dispose(notifyObject);
}
public void Dispose()
{
_timer?.Dispose();
}
}
}