v10.10.2024.0701 使用IJsonHost改进Json序列化
大石头 编写于 2024-07-01 08:36:34 大石头 提交于 2024-07-01 08:48:33
X
using System.Collections;
using System.Runtime.InteropServices;

namespace System.Threading;

[ComVisible(true)]
public sealed class Timer : MarshalByRefObject, IDisposable
{
	private sealed class TimerComparer : IComparer
	{
		public int Compare(object x, object y)
		{
			if (!(x is Timer timer))
			{
				return -1;
			}
			if (!(y is Timer timer2))
			{
				return 1;
			}
			long num = timer.next_run - timer2.next_run;
			if (num == 0)
			{
				if (x != y)
				{
					return -1;
				}
				return 0;
			}
			if (num <= 0)
			{
				return -1;
			}
			return 1;
		}
	}

	private sealed class Scheduler
	{
		private static Scheduler instance;

		private SortedList list;

		private ManualResetEvent changed;

		private static WaitCallback TimerCaller;

		public static Scheduler Instance => instance;

		static Scheduler()
		{
			TimerCaller = TimerCB;
			instance = new Scheduler();
		}

		private Scheduler()
		{
			changed = new ManualResetEvent(initialState: false);
			list = new SortedList(new TimerComparer(), 1024);
			Thread thread = new Thread(SchedulerThread);
			thread.IsBackground = true;
			thread.Start();
		}

		public void Remove(Timer timer)
		{
			if (timer.next_run == 0 || timer.next_run == long.MaxValue)
			{
				return;
			}
			lock (this)
			{
				InternalRemove(timer);
			}
		}

		public void Change(Timer timer, long new_next_run)
		{
			bool flag = false;
			lock (this)
			{
				InternalRemove(timer);
				if (new_next_run == long.MaxValue)
				{
					timer.next_run = new_next_run;
					return;
				}
				if (!timer.disposed)
				{
					timer.next_run = new_next_run;
					Add(timer);
					flag = list.GetByIndex(0) == timer;
				}
			}
			if (flag)
			{
				changed.Set();
			}
		}

		private int FindByDueTime(long nr)
		{
			int i = 0;
			int num = list.Count - 1;
			if (num < 0)
			{
				return -1;
			}
			if (num < 20)
			{
				for (; i <= num; i++)
				{
					Timer timer = (Timer)list.GetByIndex(i);
					if (timer.next_run == nr)
					{
						return i;
					}
					if (timer.next_run > nr)
					{
						return -1;
					}
				}
				return -1;
			}
			while (i <= num)
			{
				int num2 = i + (num - i >> 1);
				Timer timer2 = (Timer)list.GetByIndex(num2);
				if (nr == timer2.next_run)
				{
					return num2;
				}
				if (nr > timer2.next_run)
				{
					i = num2 + 1;
				}
				else
				{
					num = num2 - 1;
				}
			}
			return -1;
		}

		private void Add(Timer timer)
		{
			int num = FindByDueTime(timer.next_run);
			if (num != -1)
			{
				bool flag = ((long.MaxValue - timer.next_run > 20000) ? true : false);
				Timer timer2;
				do
				{
					num++;
					if (flag)
					{
						timer.next_run++;
					}
					else
					{
						timer.next_run--;
					}
					if (num >= list.Count)
					{
						break;
					}
					timer2 = (Timer)list.GetByIndex(num);
				}
				while (timer2.next_run == timer.next_run);
			}
			list.Add(timer, timer);
		}

		private int InternalRemove(Timer timer)
		{
			int num = list.IndexOfKey(timer);
			if (num >= 0)
			{
				list.RemoveAt(num);
			}
			return num;
		}

		private static void TimerCB(object o)
		{
			Timer timer = (Timer)o;
			try
			{
				timer.callback(timer.state);
			}
			catch
			{
			}
		}

		private void SchedulerThread()
		{
			Thread.CurrentThread.Name = "Timer-Scheduler";
			ArrayList arrayList = new ArrayList(512);
			while (true)
			{
				int num = -1;
				long ticks = DateTime.Now.Ticks;
				lock (this)
				{
					changed.Reset();
					int num2 = list.Count;
					int num3;
					for (num3 = 0; num3 < num2; num3++)
					{
						Timer timer = (Timer)list.GetByIndex(num3);
						if (timer.next_run > ticks)
						{
							break;
						}
						list.RemoveAt(num3);
						num2--;
						num3--;
						ThreadPool.QueueUserWorkItem(TimerCaller, timer);
						long period_ms = timer.period_ms;
						long due_time_ms = timer.due_time_ms;
						if (period_ms == -1 || ((period_ms == 0 || period_ms == -1) && due_time_ms != -1))
						{
							timer.next_run = long.MaxValue;
						}
						else
						{
							timer.next_run = DateTime.Now.Ticks + 10000 * timer.period_ms;
							arrayList.Add(timer);
						}
					}
					num2 = arrayList.Count;
					for (num3 = 0; num3 < num2; num3++)
					{
						Timer timer2 = (Timer)arrayList[num3];
						Add(timer2);
					}
					arrayList.Clear();
					ShrinkIfNeeded(arrayList, 512);
					int capacity = list.Capacity;
					num2 = list.Count;
					if (capacity > 1024 && num2 > 0 && capacity / num2 > 3)
					{
						list.Capacity = num2 * 2;
					}
					long num4 = long.MaxValue;
					if (list.Count > 0)
					{
						num4 = ((Timer)list.GetByIndex(0)).next_run;
					}
					num = -1;
					if (num4 != long.MaxValue)
					{
						long num5 = num4 - DateTime.Now.Ticks;
						num = (int)(num5 / 10000);
						if (num < 0)
						{
							num = 0;
						}
					}
				}
				changed.WaitOne(num);
			}
		}

		private void ShrinkIfNeeded(ArrayList list, int initial)
		{
			int capacity = list.Capacity;
			int count = list.Count;
			if (capacity > initial && count > 0 && capacity / count > 3)
			{
				list.Capacity = count * 2;
			}
		}
	}

	private const long MaxValue = 4294967294L;

	private static Scheduler scheduler = Scheduler.Instance;

	private TimerCallback callback;

	private object state;

	private long due_time_ms;

	private long period_ms;

	private long next_run;

	private bool disposed;

	public Timer(TimerCallback callback, object state, int dueTime, int period)
	{
		Init(callback, state, dueTime, period);
	}

	public Timer(TimerCallback callback, object state, long dueTime, long period)
	{
		Init(callback, state, dueTime, period);
	}

	public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period)
	{
		Init(callback, state, (long)dueTime.TotalMilliseconds, (long)period.TotalMilliseconds);
	}

	[CLSCompliant(false)]
	public Timer(TimerCallback callback, object state, uint dueTime, uint period)
	{
		long dueTime2 = ((dueTime == uint.MaxValue) ? (-1L) : ((long)dueTime));
		long period2 = ((period == uint.MaxValue) ? (-1L) : ((long)period));
		Init(callback, state, dueTime2, period2);
	}

	public Timer(TimerCallback callback)
	{
		Init(callback, this, -1L, -1L);
	}

	private void Init(TimerCallback callback, object state, long dueTime, long period)
	{
		if (callback == null)
		{
			throw new ArgumentNullException("callback");
		}
		this.callback = callback;
		this.state = state;
		Change(dueTime, period, first: true);
	}

	public bool Change(int dueTime, int period)
	{
		return Change(dueTime, period, first: false);
	}

	public bool Change(TimeSpan dueTime, TimeSpan period)
	{
		return Change((long)dueTime.TotalMilliseconds, (long)period.TotalMilliseconds, first: false);
	}

	[CLSCompliant(false)]
	public bool Change(uint dueTime, uint period)
	{
		long dueTime2 = ((dueTime == uint.MaxValue) ? (-1L) : ((long)dueTime));
		long period2 = ((period == uint.MaxValue) ? (-1L) : ((long)period));
		return Change(dueTime2, period2, first: false);
	}

	public void Dispose()
	{
		if (!disposed)
		{
			disposed = true;
			scheduler.Remove(this);
		}
	}

	public bool Change(long dueTime, long period)
	{
		return Change(dueTime, period, first: false);
	}

	private bool Change(long dueTime, long period, bool first)
	{
		if (dueTime > 4294967294u)
		{
			throw new ArgumentOutOfRangeException("dueTime", "Due time too large");
		}
		if (period > 4294967294u)
		{
			throw new ArgumentOutOfRangeException("period", "Period too large");
		}
		if (dueTime < -1)
		{
			throw new ArgumentOutOfRangeException("dueTime");
		}
		if (period < -1)
		{
			throw new ArgumentOutOfRangeException("period");
		}
		if (disposed)
		{
			return false;
		}
		due_time_ms = dueTime;
		period_ms = period;
		long new_next_run;
		if (dueTime == 0)
		{
			new_next_run = 0L;
		}
		else if (dueTime < 0)
		{
			new_next_run = long.MaxValue;
			if (first)
			{
				next_run = new_next_run;
				return true;
			}
		}
		else
		{
			new_next_run = dueTime * 10000 + DateTime.Now.Ticks;
		}
		scheduler.Change(this, new_next_run);
		return true;
	}

	public bool Dispose(WaitHandle notifyObject)
	{
		if (notifyObject == null)
		{
			throw new ArgumentNullException("notifyObject");
		}
		Dispose();
		return true;
	}
}