rendered paste bodypublic class TimerWheel : IDisposable
{
public const int DefaultSectorCount = 0x200;
public const int DefaultSectorSpan = 1;
private int m_currentSectorIndex;
private bool m_disposed;
private int m_sectorCount;
private List<TimerItem>[] m_sectors;
private int m_sectorSpan;
private Timer m_timer;
public const int MaxCurrentCount = 0xFF;
public const int MaxSectors = 0xFFFF;
public const int MaxSpanSeconds = 0xFFFF;
public TimerWheel()
: this(0x200, new TimeSpan(0, 0, 1))
{
}
public TimerWheel(int sectorCount, TimeSpan sectorSpan)
{
if ((sectorCount <= 0) || (sectorCount >= 0xFFFF))
throw new ArgumentOutOfRangeException("sectorCount");
int totalSeconds = TimerItem.TotalSeconds(sectorSpan);
if (totalSeconds < 1)
throw new ArgumentOutOfRangeException("sectorSpan");
m_sectorCount = sectorCount;
m_sectorSpan = totalSeconds;
m_sectors = new List<TimerItem>[m_sectorCount];
for (int i = 0; i < m_sectorCount; i++)
{
m_sectors[i] = new List<TimerItem>();
}
m_timer = new Timer((double)(m_sectorSpan * 0x3E8));
m_timer.AutoReset = true;
m_timer.Elapsed += Timer_Elapsed;
m_timer.Start();
}
public void Add(TimerItem timerItem)
{
if (timerItem == null)
throw new ArgumentNullException("timerItem");
if (timerItem.Wheel != this)
throw new InvalidOperationException("Invalid Timer Addition");
if (!timerItem.IsStarted)
{
int currentSectorIndex = m_currentSectorIndex;
int num2 = timerItem.SpanSeconds / m_sectorSpan;
timerItem.CurrentCount = (num2 / m_sectorCount) + 1;
int index = (num2 + currentSectorIndex) % m_sectorCount;
if (index == currentSectorIndex)
{
index = (index + 1) % m_sectorCount;
}
timerItem.SectorIndex = index;
lock (m_sectors[index])
{
m_sectors[index].Add(timerItem);
timerItem.SectorListIndex = m_sectors[index].Count - 1;
}
}
}
protected void CheckDisposed()
{
if (m_disposed)
{
throw new ObjectDisposedException(GetType().ToString());
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!m_disposed)
{
m_timer.Elapsed -= Timer_Elapsed;
m_timer.Dispose();
m_disposed = true;
}
}
~TimerWheel()
{
Dispose(true);
}
public TimeSpan GetRemainingTimeToExpire(TimerItem item)
{
if (item == null)
throw new ArgumentNullException("item");
if (item.Wheel != this)
throw new ArgumentException("Invalid Timer Item");
lock (m_sectors)
{
int num = (item.CurrentCount - 1) * m_sectorCount;
if (item.SectorIndex < m_currentSectorIndex)
{
num += m_currentSectorIndex - item.SectorIndex;
}
else
{
num += m_sectorCount - (m_currentSectorIndex - item.SectorIndex);
}
return new TimeSpan(0, 0, num * m_sectorSpan);
}
}
public bool Remove(TimerItem timerItem)
{
if (timerItem == null)
throw new ArgumentNullException("timerItem");
if (timerItem.Wheel != this)
throw new InvalidOperationException("Invalid Timer Removal");
if (timerItem.IsStarted)
{
int index = timerItem.SectorIndex;
if ((index < 0) || (index > m_sectors.Length))
{
return false;
}
lock (m_sectors[index])
{
int sectorListIndex = timerItem.SectorListIndex;
if ((sectorListIndex < m_sectors[index].Count) && (m_sectors[index][sectorListIndex] == timerItem))
{
if (sectorListIndex != (m_sectors[index].Count - 1))
{
TimerItem item = m_sectors[index][m_sectors[index].Count - 1];
m_sectors[index][sectorListIndex] = item;
item.SectorListIndex = sectorListIndex;
}
m_sectors[index].RemoveAt(m_sectors[index].Count - 1);
timerItem.SectorIndex = 0xFFFF;
return true;
}
return false;
}
}
return false;
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
int index;
lock (m_sectors)
{
index = m_currentSectorIndex;
m_currentSectorIndex = (m_currentSectorIndex + 1) % m_sectorCount;
}
List<TimerItem> timersToRemove = null;
int count = 0;
lock (m_sectors[index])
{
int listCount = m_sectors[index].Count;
int num4 = listCount - 1;
for (int i = num4; i >= 0; i--)
{
// handles moving timers down the list
TimerItem item = m_sectors[index][i];
if (item.DecrementCurrentCount() == 0)
{
item.SectorIndex = 0xFFFF;
TimerItem item2 = m_sectors[index][num4];
m_sectors[index][i] = item2;
item2.SectorListIndex = i;
m_sectors[index][num4--] = item;
}
}
count = (listCount - num4) - 1;
if (count > 0)
{
timersToRemove = m_sectors[index].GetRange(num4 + 1, count);
m_sectors[index].RemoveRange(num4 + 1, count);
}
}
if (timersToRemove != null)
{
foreach (TimerItem timerItem in timersToRemove)
{
System.Threading.ThreadPool.QueueUserWorkItem(timerItem.OnExpired, null);
}
}
}
}
public class TimerItem
{
private const ulong SpanSecondsMask = 0xFFFF000000000000;
private const ulong SectorIndexMask = 0x0000FFFF00000000;
private const ulong SectorListIndexMask = 0x0000000000FFFFFF;
private const ulong CurrentCountMask = 0x00000000FF000000;
private const int SectorListIndexShift = 0;
private const int CurrentCountShift = 0x18;
private const int SectorIndexShift = 0x20;
private const int SpanSecondsShift = 0x30;
private ulong m_state;
private TimerWheel m_timerWheel;
public event EventHandler Expired;
public TimerItem(TimerWheel timerWheel, TimeSpan timeSpan)
{
if (timerWheel == null)
throw new ArgumentNullException("timerWheel");
int totalSeconds = TotalSeconds(timeSpan);
if ((totalSeconds > 0xFFFF) || (totalSeconds < 1))
throw new ArgumentOutOfRangeException("timeSpan");
m_timerWheel = timerWheel;
SpanSeconds = totalSeconds;
SectorIndex = 0xFFFF;
}
public int DecrementCurrentCount()
{
int currentCount = (int)((m_state & CurrentCountMask) >> CurrentCountShift);
--currentCount;
m_state &= ~CurrentCountMask;
m_state |= (ulong)(currentCount << CurrentCountShift) & CurrentCountMask;
return currentCount;
}
internal void OnExpired(object state)
{
if (Expired != null)
{
Expired(this, EventArgs.Empty);
}
}
public void Reset()
{
Reset(TimerSpan);
}
public void Reset(TimeSpan newTimerSpan)
{
int totalSeconds = TotalSeconds(newTimerSpan);
if ((totalSeconds > 0xFFFF) || (totalSeconds < 1))
throw new ArgumentOutOfRangeException("newTimerSpan");
lock (this)
{
if (IsStarted)
{
m_timerWheel.Remove(this);
}
SpanSeconds = totalSeconds;
SectorIndex = 0xFFFF;
m_timerWheel.Add(this);
}
}
public void Start()
{
lock (this)
{
if (!IsStarted)
{
m_timerWheel.Add(this);
}
}
}
public void Stop()
{
lock (this)
{
if (IsStarted)
{
m_timerWheel.Remove(this);
}
}
}
internal static int TotalSeconds(TimeSpan timeSpan)
{
return (int)(timeSpan.Ticks / ((long)0x989680));
}
public int CurrentCount
{
get
{
return (int)((m_state & CurrentCountMask) >> CurrentCountShift);
}
set
{
if (value > 0xFF)
throw new ArgumentOutOfRangeException("value");
m_state &= ~CurrentCountMask;
m_state |= (((ulong)value) << CurrentCountShift) & CurrentCountMask;
}
}
public bool IsStarted
{
get { return (SectorIndex != 0xFFFF); }
}
public TimeSpan RemainingTime
{
get { return m_timerWheel.GetRemainingTimeToExpire(this); }
}
public int SectorIndex
{
get
{
return (int)((m_state & SectorIndexMask) >> SectorIndexShift);
}
set
{
if (value > 0xFFFF)
throw new ArgumentOutOfRangeException("value");
m_state &= ~SectorIndexMask;//0xFFFF0000FFFFFFFF;
m_state |= (ulong)(((ulong)value << SectorIndexShift) & SectorIndexMask);
}
}
public int SectorListIndex
{
get
{
//return (((int)m_state) & 0xFFFFFF);
return (int)(m_state & SectorListIndexMask);
}
set
{
//m_state &= 0xFFFFFFFFFF000000;
m_state &= ~SectorListIndexMask;
//m_state |= (ulong)(value & 0xFFFFFF);
m_state |= (ulong)value & SectorListIndexMask;
}
}
public int SpanSeconds
{
get
{
return (int)((m_state & SpanSecondsMask) >> SpanSecondsShift);
}
private set
{
if (value > 0xFFFF)
throw new ArgumentOutOfRangeException("value");
m_state &= ~SpanSecondsMask;
m_state |= (ulong)((ulong)(value << SpanSecondsShift) & SpanSecondsMask);
}
}
internal ulong State
{
get { return m_state; }
}
public TimeSpan TimerSpan
{
get { return new TimeSpan(0, 0, SpanSeconds); }
}
public TimerWheel Wheel
{
get { return m_timerWheel; }
}
}