Decompiled source of Adaptive Trigger For PSVR2 v1.0.0

Niko666.Adaptive_Trigger_For_PSVR2.dll

Decompiled a month ago
using System;
using System.CodeDom.Compiler;
using System.Configuration;
using System.Diagnostics;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PSVR2Toolkit.CAPI;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("Niko666")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Implemented some Adaptive Trigger effects for chad PSVR2 controller enjoyers. REQUIRES PSVR2 Toolkit TO USE!")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Niko666.Adaptive_Trigger_For_PSVR2")]
[assembly: AssemblyTitle("Adaptive_Trigger_For_PSVR2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace Niko666
{
	[BepInProcess("h3vr.exe")]
	[BepInPlugin("Niko666.Adaptive_Trigger_For_PSVR2", "Adaptive_Trigger_For_PSVR2", "1.0.0")]
	public class AdaptiveTrigger : BaseUnityPlugin
	{
		public static ConfigEntry<byte> ClickyEffectStrength;

		public static ConfigEntry<byte> RecoilFeedbackStrength;

		public static ConfigEntry<bool> UseVibrationFeedbackForRecoil;

		public static ConfigEntry<byte> VibrationFrequency;

		public static int _shotsSoFar;

		public const string Id = "Niko666.Adaptive_Trigger_For_PSVR2";

		internal static ManualLogSource Logger { get; private set; }

		public static string Name => "Adaptive_Trigger_For_PSVR2";

		public static string Version => "1.0.0";

		public void Awake()
		{
			ClickyEffectStrength = ((BaseUnityPlugin)this).Config.Bind<byte>("General", "ClickyEffectStrength", (byte)4, "Effect strength of clicky trigger effect. (0-8)");
			RecoilFeedbackStrength = ((BaseUnityPlugin)this).Config.Bind<byte>("General", "RecoilFeedbackStrength", (byte)8, "Effect strength of firearm recoil effect. (0-8)");
			UseVibrationFeedbackForRecoil = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UseVibrationFeedbackForRecoil", false, "Use vibration-based feedback for recoil effect. By default the mod use force-based feedback to emulate the recoil \"kick\" effect, but it doesn't work well with high rate of fire weapons when doing full-auto shooting. Turning this option on will make the trigger vibrates instead of kicking, which is more suitable for full-auto shooting but worse the feeling when single-shot. ");
			VibrationFrequency = ((BaseUnityPlugin)this).Config.Bind<byte>("General", "VibrationFrequency", (byte)50, "Vibration frequency for recoil effect when 'UseVibrationFeedbackForRecoil' is enabled. (1-255)");
			Logger = ((BaseUnityPlugin)this).Logger;
			if (!IpcClient.Instance().IsRunning)
			{
				if (IpcClient.Instance().Start())
				{
					Logger.LogMessage((object)"PSVR2 Toolkit IPC Connected.");
					Harmony.CreateAndPatchAll(typeof(AdaptiveTriggerPatch), (string)null);
					Logger.LogMessage((object)("Fuck this world! Sent from Niko666.Adaptive_Trigger_For_PSVR2 " + Version));
				}
				else
				{
					Logger.LogMessage((object)"Failed to connect PSVR2 Toolkit IPC. Did you install PSVR2 Toolkit properly?");
				}
			}
		}

		public void OnDestroy()
		{
			IpcClient.Instance().TriggerEffectDisable(EVRControllerType.Both);
			Thread.Sleep(20);
			IpcClient.Instance().Stop();
			Logger.LogMessage((object)"PSVR2 Toolkit IPC disconnected. It is now safe to turn off your computer.");
		}

		public static void ShotFired(FVRFireArm fireArm)
		{
			if ((Object)(object)((FVRInteractiveObject)fireArm).m_hand != (Object)null)
			{
				_shotsSoFar++;
			}
		}
	}
	internal class AdaptiveTriggerPatch : MonoBehaviour
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static ShotFired <0>__ShotFired;
		}

		[HarmonyPatch(typeof(FVRViveHand), "Update")]
		[HarmonyPostfix]
		public static void ClearEffectOnDrop(FVRViveHand __instance)
		{
			bool flag = false;
			if ((Object)(object)__instance.CurrentInteractable == (Object)null && !flag)
			{
				IpcClient.Instance().TriggerEffectDisable(__instance.IsThisTheRightHand ? EVRControllerType.Right : EVRControllerType.Left);
				flag = true;
			}
			else
			{
				flag = false;
			}
		}

		[HarmonyPatch(typeof(FVRFireArm), "Awake")]
		[HarmonyPostfix]
		public static void ShotDetect(FVRFireArm __instance)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			FVRSceneSettings currentSceneSettings = GM.CurrentSceneSettings;
			object obj = <>O.<0>__ShotFired;
			if (obj == null)
			{
				ShotFired val = AdaptiveTrigger.ShotFired;
				<>O.<0>__ShotFired = val;
				obj = (object)val;
			}
			currentSceneSettings.ShotFiredEvent += (ShotFired)obj;
		}

		[HarmonyPatch(typeof(FVRFireArm), "FVRUpdate")]
		[HarmonyPostfix]
		public static void GlobalRecoilEffect(FVRFireArm __instance)
		{
			byte b = 2;
			byte b2 = 7;
			bool flag = false;
			if ((Object)(object)((FVRInteractiveObject)__instance).m_hand != (Object)null)
			{
				if (!flag)
				{
					ClosedBoltWeapon val = (ClosedBoltWeapon)(object)((__instance is ClosedBoltWeapon) ? __instance : null);
					if (val == null)
					{
						OpenBoltReceiver val2 = (OpenBoltReceiver)(object)((__instance is OpenBoltReceiver) ? __instance : null);
						if (val2 == null)
						{
							Handgun val3 = (Handgun)(object)((__instance is Handgun) ? __instance : null);
							if (val3 == null)
							{
								TubeFedShotgun val4 = (TubeFedShotgun)(object)((__instance is TubeFedShotgun) ? __instance : null);
								if (val4 == null)
								{
									BoltActionRifle val5 = (BoltActionRifle)(object)((__instance is BoltActionRifle) ? __instance : null);
									if (val5 == null)
									{
										if (!(__instance is BreakActionWeapon))
										{
											if (!(__instance is Revolver))
											{
												SingleActionRevolver val6 = (SingleActionRevolver)(object)((__instance is SingleActionRevolver) ? __instance : null);
												if (val6 == null)
												{
													RevolvingShotgun val7 = (RevolvingShotgun)(object)((__instance is RevolvingShotgun) ? __instance : null);
													if (val7 == null)
													{
														LAPD2019 val8 = (LAPD2019)(object)((__instance is LAPD2019) ? __instance : null);
														if (val8 == null)
														{
															BAP val9 = (BAP)(object)((__instance is BAP) ? __instance : null);
															if (val9 == null)
															{
																if (!(__instance is PotatoGun))
																{
																	GrappleGun val10 = (GrappleGun)(object)((__instance is GrappleGun) ? __instance : null);
																	if (val10 == null)
																	{
																		Airgun val11 = (Airgun)(object)((__instance is Airgun) ? __instance : null);
																		if (val11 == null)
																		{
																			CarlGustaf val12 = (CarlGustaf)(object)((__instance is CarlGustaf) ? __instance : null);
																			if (val12 == null)
																			{
																				RailTater val13 = (RailTater)(object)((__instance is RailTater) ? __instance : null);
																				if (val13 == null)
																				{
																					FlameThrower val14 = (FlameThrower)(object)((__instance is FlameThrower) ? __instance : null);
																					if (val14 == null)
																					{
																						sblp val15 = (sblp)(object)((__instance is sblp) ? __instance : null);
																						if (val15 != null)
																						{
																							b = (byte)(val15.TriggerResetThreshold * 10f - 1f);
																							b2 = (byte)(val15.TriggerFiringThreshold * 10f - 1f);
																						}
																						else
																						{
																							b = 2;
																							b2 = 7;
																						}
																					}
																					else
																					{
																						b = 3;
																						b2 = (byte)(val14.TriggerFiringThreshold * 10f - 1f);
																					}
																				}
																				else
																				{
																					b = (byte)(val13.TriggerResetThreshold * 10f - 1f);
																					b2 = (byte)(val13.TriggerFiringThreshold * 10f - 1f);
																				}
																			}
																			else
																			{
																				b = (byte)(val12.TriggerResetThreshold * 10f - 1f);
																				b2 = (byte)(val12.TriggerFiringThreshold * 10f - 1f);
																			}
																		}
																		else
																		{
																			b = (byte)(val11.TriggerResetThreshold * 10f - 1f);
																			b2 = (byte)(val11.TriggerFiringThreshold * 10f - 1f);
																		}
																	}
																	else
																	{
																		b = (byte)(val10.TriggerResetThreshold * 10f - 1f);
																		b2 = (byte)(val10.TriggerBreakThreshold * 10f - 1f);
																	}
																}
																else
																{
																	b = 4;
																	b2 = 7;
																}
															}
															else
															{
																b = (byte)(val9.TriggerResetThreshold * 10f - 1f);
																b2 = (byte)(val9.TriggerFiringThreshold * 10f - 1f);
															}
														}
														else
														{
															b = (byte)(val8.TriggerResetThreshold * 10f - 1f);
															b2 = (byte)(val8.TriggerFireThreshold * 10f - 1f);
														}
													}
													else
													{
														b = (byte)(val7.TriggerResetThreshold * 10f - 1f);
														b2 = (byte)(val7.TriggerFiringThreshold * 10f - 1f);
													}
												}
												else
												{
													b = (byte)(val6.TriggerThreshold * 10f - 2f);
													b2 = (byte)(val6.TriggerThreshold * 10f - 1f);
												}
											}
											else
											{
												b = 2;
												b2 = 9;
											}
										}
										else
										{
											b = 4;
											b2 = 7;
										}
									}
									else
									{
										b = (byte)(val5.TriggerResetThreshold * 10f - 1f);
										b2 = (byte)(val5.TriggerFiringThreshold * 10f - 1f);
									}
								}
								else
								{
									b = (byte)(val4.TriggerResetThreshold * 10f - 1f);
									b2 = (byte)(val4.TriggerBreakThreshold * 10f - 1f);
								}
							}
							else
							{
								b = (byte)(val3.TriggerResetThreshold * 10f - 1f);
								b2 = (byte)(val3.TriggerBreakThreshold * 10f - 1f);
							}
						}
						else
						{
							b = (byte)(val2.TriggerResetThreshold * 10f - 1f);
							b2 = (byte)(val2.TriggerFiringThreshold * 10f - 1f);
						}
					}
					else
					{
						b = (byte)(val.TriggerResetThreshold * 10f - 1f);
						b2 = (byte)(val.TriggerFiringThreshold * 10f - 1f);
					}
					flag = true;
				}
				if (AdaptiveTrigger._shotsSoFar != 0)
				{
					if (AdaptiveTrigger.UseVibrationFeedbackForRecoil.Value)
					{
						IpcClient.Instance().TriggerEffectVibration(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? EVRControllerType.Right : EVRControllerType.Left, (byte)(b - 1), AdaptiveTrigger.RecoilFeedbackStrength.Value, AdaptiveTrigger.VibrationFrequency.Value);
					}
					else
					{
						IpcClient.Instance().TriggerEffectFeedback(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? EVRControllerType.Right : EVRControllerType.Left, (byte)(b - 1), AdaptiveTrigger.RecoilFeedbackStrength.Value);
					}
					if (((FVRInteractiveObject)__instance).m_hand.m_buzztime > 0.02f)
					{
						IpcClient.Instance().TriggerEffectSlopeFeedback(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? EVRControllerType.Right : EVRControllerType.Left, (byte)(b - 1), (byte)(b2 - 1), 1, AdaptiveTrigger.ClickyEffectStrength.Value);
						AdaptiveTrigger._shotsSoFar = 0;
					}
				}
				else
				{
					IpcClient.Instance().TriggerEffectSlopeFeedback(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? EVRControllerType.Right : EVRControllerType.Left, (byte)(b - 1), (byte)(b2 - 1), 1, AdaptiveTrigger.ClickyEffectStrength.Value);
				}
			}
			else
			{
				flag = false;
			}
		}
	}
}
namespace PSVR2Toolkit.CAPI
{
	public class IpcClient
	{
		private const ushort IPC_SERVER_PORT = 3364;

		private const ushort k_unIpcVersion = 2;

		private static IpcClient m_pInstance;

		private bool m_running;

		private TcpClient? m_client;

		private NetworkStream? m_stream;

		private Thread? m_receiveThread;

		private readonly object m_gazeStateLock = new object();

		private TaskCompletionSource<CommandDataServerGazeDataResult>? m_gazeTask;

		private CancellationTokenSource m_forceShutdownToken;

		private ushort m_serverIpcVersion = 2;

		private int m_gazePumpPeriodMs = 8;

		private CommandDataServerGazeDataResult2? m_lastGazeState;

		public bool IsRunning => m_running;

		public static IpcClient Instance()
		{
			if (m_pInstance == null)
			{
				m_pInstance = new IpcClient();
			}
			return m_pInstance;
		}

		public bool Start()
		{
			if (m_running)
			{
				return false;
			}
			try
			{
				m_client = new TcpClient();
				m_client.Connect("127.0.0.1", 3364);
				if (m_client.Connected)
				{
					m_stream = m_client.GetStream();
					m_running = true;
					m_forceShutdownToken = new CancellationTokenSource();
					m_receiveThread = new Thread((ThreadStart)delegate
					{
						ReceiveLoop(m_forceShutdownToken.Token);
					});
					m_receiveThread.Start();
					return true;
				}
				return false;
			}
			catch (SocketException ex)
			{
				Console.WriteLine($"[IPC_CLIENT] Connection failed. LastError = {ex.SocketErrorCode}");
				return false;
			}
		}

		public void Stop()
		{
			if (m_running)
			{
				m_running = false;
				m_forceShutdownToken.Cancel();
				lock (m_gazeStateLock)
				{
					m_gazeTask?.TrySetCanceled();
					m_gazeTask = null;
				}
				try
				{
					m_stream?.Close();
					m_client?.Close();
				}
				catch
				{
				}
				if (m_receiveThread != null && m_receiveThread.IsAlive && !m_receiveThread.Join(2000))
				{
					m_receiveThread.Interrupt();
				}
				m_stream?.Dispose();
				m_client?.Close();
				m_forceShutdownToken.Dispose();
			}
		}

		private void ReceiveLoop(CancellationToken token)
		{
			byte[] array = new byte[1024];
			try
			{
				Socket client = m_client.Client;
				m_stream.ReadTimeout = 1;
				CommandDataClientRequestHandshake commandDataClientRequestHandshake = default(CommandDataClientRequestHandshake);
				commandDataClientRequestHandshake.ipcVersion = 2;
				commandDataClientRequestHandshake.processId = (uint)Process.GetCurrentProcess().Id;
				CommandDataClientRequestHandshake data = commandDataClientRequestHandshake;
				SendIpcCommand(ECommandType.ClientRequestHandshake, data);
				Stopwatch stopwatch = Stopwatch.StartNew();
				long num = stopwatch.ElapsedMilliseconds;
				while (m_running && !token.IsCancellationRequested)
				{
					long elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
					if (elapsedMilliseconds >= num)
					{
						SendIpcCommand(ECommandType.ClientRequestGazeData);
						num = elapsedMilliseconds + m_gazePumpPeriodMs;
					}
					if (client.Poll(1000, SelectMode.SelectRead) && client.Available > 0)
					{
						int available = client.Available;
						if (available > array.Length)
						{
							array = new byte[Math.Max(available, array.Length * 2)];
						}
						int num2 = m_stream.Read(array, 0, Math.Min(array.Length, available));
						if (num2 <= 0)
						{
							Console.WriteLine("[IPC_CLIENT] Disconnected from server.");
							break;
						}
						if (num2 < Marshal.SizeOf(typeof(CommandHeader)))
						{
							Console.WriteLine("[IPC_CLIENT] Received invalid command header size.");
						}
						else
						{
							HandleIpcCommand(array, num2);
						}
					}
					else
					{
						Thread.Sleep(1);
					}
				}
			}
			catch (Exception ex)
			{
				if (m_running)
				{
					Console.WriteLine("[IPC_CLIENT] Error in receive loop: " + ex.Message);
				}
			}
		}

		private GazeEyeResult2 UpgradeGazeEyeResult(GazeEyeResult eye)
		{
			GazeEyeResult2 result = default(GazeEyeResult2);
			result.isGazeOriginValid = eye.isGazeOriginValid;
			result.gazeOriginMm = eye.gazeOriginMm;
			result.isGazeDirValid = eye.isGazeDirValid;
			result.gazeDirNorm = eye.gazeDirNorm;
			result.isPupilDiaValid = eye.isPupilDiaValid;
			result.pupilDiaMm = eye.pupilDiaMm;
			result.isBlinkValid = eye.isBlinkValid;
			result.blink = eye.blink;
			result.isOpenEnabled = false;
			result.open = 0f;
			return result;
		}

		private CommandDataServerGazeDataResult2 UpgradeGazeDataResult(CommandDataServerGazeDataResult result)
		{
			CommandDataServerGazeDataResult2 result2 = default(CommandDataServerGazeDataResult2);
			result2.leftEye = UpgradeGazeEyeResult(result.leftEye);
			result2.rightEye = UpgradeGazeEyeResult(result.rightEye);
			return result2;
		}

		private void HandleIpcCommand(byte[] pBuffer, int bytesReceived)
		{
			CommandHeader commandHeader = ByteArrayToStructure<CommandHeader>(pBuffer, 0);
			switch (commandHeader.type)
			{
			case ECommandType.ServerPong:
				Console.WriteLine("[IPC_CLIENT] Received Pong from server.");
				break;
			case ECommandType.ServerHandshakeResult:
				if (commandHeader.dataLen == Marshal.SizeOf(typeof(CommandDataServerHandshakeResult)))
				{
					CommandDataServerHandshakeResult commandDataServerHandshakeResult = ByteArrayToStructure<CommandDataServerHandshakeResult>(pBuffer, Marshal.SizeOf(typeof(CommandHeader)));
					m_serverIpcVersion = commandDataServerHandshakeResult.ipcVersion;
					switch (commandDataServerHandshakeResult.result)
					{
					case EHandshakeResult.Success:
						Console.WriteLine("[IPC_CLIENT] Handshake successful!");
						break;
					case EHandshakeResult.Failed:
						Console.WriteLine("[IPC_CLIENT] Handshake failed!");
						break;
					case EHandshakeResult.Outdated:
						Console.WriteLine($"[IPC_CLIENT] Handshake failed with reason: Outdated client. Please upgrade to an IPC version of {commandDataServerHandshakeResult.ipcVersion}");
						break;
					}
				}
				break;
			case ECommandType.ServerGazeDataResult:
				if (m_serverIpcVersion == 1)
				{
					if (commandHeader.dataLen == Marshal.SizeOf(typeof(CommandDataServerGazeDataResult)))
					{
						CommandDataServerGazeDataResult result = ByteArrayToStructure<CommandDataServerGazeDataResult>(pBuffer, Marshal.SizeOf(typeof(CommandHeader)));
						m_lastGazeState = UpgradeGazeDataResult(result);
					}
				}
				else if (commandHeader.dataLen == Marshal.SizeOf(typeof(CommandDataServerGazeDataResult2)))
				{
					CommandDataServerGazeDataResult2 value = ByteArrayToStructure<CommandDataServerGazeDataResult2>(pBuffer, Marshal.SizeOf(typeof(CommandHeader)));
					m_lastGazeState = value;
				}
				break;
			case ECommandType.ClientRequestHandshake:
			case ECommandType.ClientRequestGazeData:
				break;
			}
		}

		private void SendIpcCommand<T>(ECommandType type, T data = default(T)) where T : struct
		{
			if (m_running)
			{
				int num = ((!data.Equals(default(T))) ? Marshal.SizeOf(typeof(T)) : 0);
				byte[] array = new byte[Marshal.SizeOf(typeof(CommandHeader)) + num];
				CommandHeader commandHeader = default(CommandHeader);
				commandHeader.type = type;
				commandHeader.dataLen = num;
				CommandHeader commandHeader2 = commandHeader;
				IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CommandHeader)));
				Marshal.StructureToPtr((object)commandHeader2, intPtr, fDeleteOld: false);
				Marshal.Copy(intPtr, array, 0, Marshal.SizeOf(typeof(CommandHeader)));
				Marshal.FreeHGlobal(intPtr);
				if (num > 0)
				{
					IntPtr intPtr2 = Marshal.AllocHGlobal(num);
					Marshal.StructureToPtr((object)data, intPtr2, fDeleteOld: false);
					Marshal.Copy(intPtr2, array, Marshal.SizeOf(typeof(CommandHeader)), num);
					Marshal.FreeHGlobal(intPtr2);
				}
				m_stream.Write(array, 0, array.Length);
			}
		}

		private void SendIpcCommand(ECommandType type)
		{
			if (m_running)
			{
				byte[] array = new byte[Marshal.SizeOf(typeof(CommandHeader))];
				CommandHeader commandHeader = default(CommandHeader);
				commandHeader.type = type;
				commandHeader.dataLen = 0;
				CommandHeader commandHeader2 = commandHeader;
				IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CommandHeader)));
				Marshal.StructureToPtr((object)commandHeader2, intPtr, fDeleteOld: false);
				Marshal.Copy(intPtr, array, 0, Marshal.SizeOf(typeof(CommandHeader)));
				Marshal.FreeHGlobal(intPtr);
				m_stream.Write(array, 0, array.Length);
			}
		}

		private T ByteArrayToStructure<T>(byte[] bytes, int offset) where T : struct
		{
			int num = Marshal.SizeOf(typeof(T));
			if (num > bytes.Length - offset)
			{
				throw new ArgumentException("Byte array is too small to contain the structure.");
			}
			IntPtr intPtr = Marshal.AllocHGlobal(num);
			Marshal.Copy(bytes, offset, intPtr, num);
			T result = (T)Marshal.PtrToStructure(intPtr, typeof(T));
			Marshal.FreeHGlobal(intPtr);
			return result;
		}

		public CommandDataServerGazeDataResult2 RequestEyeTrackingData()
		{
			if (!m_running)
			{
				return default(CommandDataServerGazeDataResult2);
			}
			return m_lastGazeState.GetValueOrDefault();
		}

		public void TriggerEffectDisable(EVRControllerType controllerType)
		{
			if (m_running)
			{
				CommandDataClientTriggerEffectOff commandDataClientTriggerEffectOff = default(CommandDataClientTriggerEffectOff);
				commandDataClientTriggerEffectOff.controllerType = controllerType;
				CommandDataClientTriggerEffectOff data = commandDataClientTriggerEffectOff;
				SendIpcCommand(ECommandType.ClientTriggerEffectOff, data);
			}
		}

		public void TriggerEffectFeedback(EVRControllerType controllerType, byte position, byte strength)
		{
			if (m_running)
			{
				CommandDataClientTriggerEffectFeedback commandDataClientTriggerEffectFeedback = default(CommandDataClientTriggerEffectFeedback);
				commandDataClientTriggerEffectFeedback.controllerType = controllerType;
				commandDataClientTriggerEffectFeedback.position = position;
				commandDataClientTriggerEffectFeedback.strength = strength;
				CommandDataClientTriggerEffectFeedback data = commandDataClientTriggerEffectFeedback;
				SendIpcCommand(ECommandType.ClientTriggerEffectFeedback, data);
			}
		}

		public void TriggerEffectWeapon(EVRControllerType controllerType, byte startPosition, byte endPosition, byte strength)
		{
			if (m_running)
			{
				CommandDataClientTriggerEffectWeapon commandDataClientTriggerEffectWeapon = default(CommandDataClientTriggerEffectWeapon);
				commandDataClientTriggerEffectWeapon.controllerType = controllerType;
				commandDataClientTriggerEffectWeapon.startPosition = startPosition;
				commandDataClientTriggerEffectWeapon.endPosition = endPosition;
				commandDataClientTriggerEffectWeapon.strength = strength;
				CommandDataClientTriggerEffectWeapon data = commandDataClientTriggerEffectWeapon;
				SendIpcCommand(ECommandType.ClientTriggerEffectWeapon, data);
			}
		}

		public void TriggerEffectVibration(EVRControllerType controllerType, byte position, byte amplitude, byte frequency)
		{
			if (m_running)
			{
				CommandDataClientTriggerEffectVibration commandDataClientTriggerEffectVibration = default(CommandDataClientTriggerEffectVibration);
				commandDataClientTriggerEffectVibration.controllerType = controllerType;
				commandDataClientTriggerEffectVibration.position = position;
				commandDataClientTriggerEffectVibration.amplitude = amplitude;
				commandDataClientTriggerEffectVibration.frequency = frequency;
				CommandDataClientTriggerEffectVibration data = commandDataClientTriggerEffectVibration;
				SendIpcCommand(ECommandType.ClientTriggerEffectVibration, data);
			}
		}

		public void TriggerEffectMultiplePositionFeedback(EVRControllerType controllerType, byte[] strength)
		{
			if (m_running)
			{
				CommandDataClientTriggerEffectMultiplePositionFeedback commandDataClientTriggerEffectMultiplePositionFeedback = default(CommandDataClientTriggerEffectMultiplePositionFeedback);
				commandDataClientTriggerEffectMultiplePositionFeedback.controllerType = controllerType;
				commandDataClientTriggerEffectMultiplePositionFeedback.strength = strength;
				CommandDataClientTriggerEffectMultiplePositionFeedback data = commandDataClientTriggerEffectMultiplePositionFeedback;
				SendIpcCommand(ECommandType.ClientTriggerEffectMultiplePositionFeedback, data);
			}
		}

		public void TriggerEffectSlopeFeedback(EVRControllerType controllerType, byte startPosition, byte endPosition, byte startStrength, byte endStrength)
		{
			if (m_running)
			{
				CommandDataClientTriggerEffectSlopeFeedback commandDataClientTriggerEffectSlopeFeedback = default(CommandDataClientTriggerEffectSlopeFeedback);
				commandDataClientTriggerEffectSlopeFeedback.controllerType = controllerType;
				commandDataClientTriggerEffectSlopeFeedback.startPosition = startPosition;
				commandDataClientTriggerEffectSlopeFeedback.endPosition = endPosition;
				commandDataClientTriggerEffectSlopeFeedback.startStrength = startStrength;
				commandDataClientTriggerEffectSlopeFeedback.endStrength = endStrength;
				CommandDataClientTriggerEffectSlopeFeedback data = commandDataClientTriggerEffectSlopeFeedback;
				SendIpcCommand(ECommandType.ClientTriggerEffectSlopeFeedback, data);
			}
		}

		public void TriggerEffectMultiplePositionVibration(EVRControllerType controllerType, byte frequency, byte[] amplitude)
		{
			if (m_running)
			{
				CommandDataClientTriggerEffectMultiplePositionVibration commandDataClientTriggerEffectMultiplePositionVibration = default(CommandDataClientTriggerEffectMultiplePositionVibration);
				commandDataClientTriggerEffectMultiplePositionVibration.controllerType = controllerType;
				commandDataClientTriggerEffectMultiplePositionVibration.frequency = frequency;
				commandDataClientTriggerEffectMultiplePositionVibration.amplitude = amplitude;
				CommandDataClientTriggerEffectMultiplePositionVibration data = commandDataClientTriggerEffectMultiplePositionVibration;
				SendIpcCommand(ECommandType.ClientTriggerEffectMultiplePositionVibration, data);
			}
		}
	}
	public enum ECommandType : ushort
	{
		ClientPing,
		ServerPong,
		ClientRequestHandshake,
		ServerHandshakeResult,
		ClientRequestGazeData,
		ServerGazeDataResult,
		ClientTriggerEffectOff,
		ClientTriggerEffectFeedback,
		ClientTriggerEffectWeapon,
		ClientTriggerEffectVibration,
		ClientTriggerEffectMultiplePositionFeedback,
		ClientTriggerEffectSlopeFeedback,
		ClientTriggerEffectMultiplePositionVibration
	}
	public enum EHandshakeResult : byte
	{
		Failed,
		Success,
		Outdated
	}
	public enum EVRControllerType : byte
	{
		Left,
		Right,
		Both
	}
	public struct CommandDataClientRequestHandshake
	{
		public ushort ipcVersion;

		public uint processId;
	}
	public struct CommandDataServerHandshakeResult
	{
		public EHandshakeResult result;

		public ushort ipcVersion;
	}
	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	public struct GazeVector3
	{
		public float x;

		public float y;

		public float z;
	}
	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	public struct GazeEyeResult
	{
		[MarshalAs(UnmanagedType.I1)]
		public bool isGazeOriginValid;

		public GazeVector3 gazeOriginMm;

		[MarshalAs(UnmanagedType.I1)]
		public bool isGazeDirValid;

		public GazeVector3 gazeDirNorm;

		[MarshalAs(UnmanagedType.I1)]
		public bool isPupilDiaValid;

		public float pupilDiaMm;

		[MarshalAs(UnmanagedType.I1)]
		public bool isBlinkValid;

		[MarshalAs(UnmanagedType.I1)]
		public bool blink;
	}
	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	public struct GazeEyeResult2
	{
		[MarshalAs(UnmanagedType.I1)]
		public bool isGazeOriginValid;

		public GazeVector3 gazeOriginMm;

		[MarshalAs(UnmanagedType.I1)]
		public bool isGazeDirValid;

		public GazeVector3 gazeDirNorm;

		[MarshalAs(UnmanagedType.I1)]
		public bool isPupilDiaValid;

		public float pupilDiaMm;

		[MarshalAs(UnmanagedType.I1)]
		public bool isBlinkValid;

		[MarshalAs(UnmanagedType.I1)]
		public bool blink;

		[MarshalAs(UnmanagedType.I1)]
		public bool isOpenEnabled;

		public float open;
	}
	public struct CommandDataServerGazeDataResult
	{
		public GazeEyeResult leftEye;

		public GazeEyeResult rightEye;
	}
	public struct CommandDataServerGazeDataResult2
	{
		public GazeEyeResult2 leftEye;

		public GazeEyeResult2 rightEye;
	}
	public struct CommandHeader
	{
		public ECommandType type;

		public int dataLen;
	}
	public struct CommandDataClientTriggerEffectOff
	{
		public EVRControllerType controllerType;
	}
	public struct CommandDataClientTriggerEffectFeedback
	{
		public EVRControllerType controllerType;

		public byte position;

		public byte strength;
	}
	public struct CommandDataClientTriggerEffectWeapon
	{
		public EVRControllerType controllerType;

		public byte startPosition;

		public byte endPosition;

		public byte strength;
	}
	public struct CommandDataClientTriggerEffectVibration
	{
		public EVRControllerType controllerType;

		public byte position;

		public byte amplitude;

		public byte frequency;
	}
	public struct CommandDataClientTriggerEffectMultiplePositionFeedback
	{
		public EVRControllerType controllerType;

		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
		public byte[] strength;
	}
	public struct CommandDataClientTriggerEffectSlopeFeedback
	{
		public EVRControllerType controllerType;

		public byte startPosition;

		public byte endPosition;

		public byte startStrength;

		public byte endStrength;
	}
	public struct CommandDataClientTriggerEffectMultiplePositionVibration
	{
		public EVRControllerType controllerType;

		public byte frequency;

		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
		public byte[] amplitude;
	}
}
namespace plugin.Properties
{
	[CompilerGenerated]
	[GeneratedCode("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
	internal sealed class Settings : ApplicationSettingsBase
	{
		private static Settings defaultInstance = (Settings)(object)SettingsBase.Synchronized((SettingsBase)(object)new Settings());

		public static Settings Default => defaultInstance;
	}
}

System.Threading.Tasks.NET35.dll

Decompiled a month ago
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Concurrent.Partitioners;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security;
using System.Text;
using System.Threading;

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyFileVersion("3.0.2.0")]
[assembly: AssemblyCompany("Robert McLaws")]
[assembly: Guid("693242a3-2f03-494f-b531-ab6265dfeedb")]
[assembly: AssemblyTitle("System.Threading.Tasks.NET35")]
[assembly: AssemblyDescription("The Mono port of the Task Parallel Library ported to .NET 3.5")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("System.Threading.Tasks.NET35")]
[assembly: AssemblyCopyright("Copyright © 2011 Robert McLaws. Contains code originally Copyright © 2009-2012 Xamarin.")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("3.0.2.0")]
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)
		{
			Init(callback, state, (dueTime == uint.MaxValue) ? (-1L) : ((long)dueTime), (period == uint.MaxValue) ? (-1L) : ((long)period));
		}

		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;
		}
	}
}
namespace System.Collections.Concurrent
{
	internal class SplitOrderedList<TKey, T>
	{
		private class Node
		{
			public bool Marked;

			public ulong Key;

			public TKey SubKey;

			public T Data;

			public Node Next;

			public Node Init(ulong key, TKey subKey, T data)
			{
				Key = key;
				SubKey = subKey;
				Data = data;
				Marked = false;
				Next = null;
				return this;
			}

			public Node Init(ulong key)
			{
				Key = key;
				Data = default(T);
				Next = null;
				Marked = false;
				SubKey = default(TKey);
				return this;
			}

			public Node Init(Node wrapped)
			{
				Marked = true;
				Next = wrapped;
				Key = 0uL;
				Data = default(T);
				SubKey = default(TKey);
				return this;
			}
		}

		private class NodeObjectPool : ObjectPool<Node>
		{
			protected override Node Creator()
			{
				return new Node();
			}
		}

		private struct SimpleRwLock
		{
			private const int RwWait = 1;

			private const int RwWrite = 2;

			private const int RwRead = 4;

			private int rwlock;

			public void EnterReadLock()
			{
				SpinWait spinWait = default(SpinWait);
				while (true)
				{
					if ((rwlock & 3) > 0)
					{
						spinWait.SpinOnce();
						continue;
					}
					if ((Interlocked.Add(ref rwlock, 4) & 1) == 0)
					{
						break;
					}
					Interlocked.Add(ref rwlock, -4);
				}
			}

			public void ExitReadLock()
			{
				Interlocked.Add(ref rwlock, -4);
			}

			public void EnterWriteLock()
			{
				SpinWait spinWait = default(SpinWait);
				while (true)
				{
					int num = rwlock;
					if (num < 2)
					{
						if (Interlocked.CompareExchange(ref rwlock, 2, num) == num)
						{
							break;
						}
						num = rwlock;
					}
					while ((num & 1) == 0 && Interlocked.CompareExchange(ref rwlock, num | 1, num) != num)
					{
						num = rwlock;
					}
					while (rwlock > 1)
					{
						spinWait.SpinOnce();
					}
				}
			}

			public void ExitWriteLock()
			{
				Interlocked.Add(ref rwlock, -2);
			}
		}

		private const int MaxLoad = 5;

		private const uint BucketSize = 512u;

		private static readonly NodeObjectPool pool = new NodeObjectPool();

		private Node head;

		private Node tail;

		private Node[] buckets = new Node[512];

		private int count;

		private int size = 2;

		private SimpleRwLock slim = default(SimpleRwLock);

		private readonly IEqualityComparer<TKey> comparer;

		private static readonly byte[] reverseTable = new byte[256]
		{
			0, 128, 64, 192, 32, 160, 96, 224, 16, 144,
			80, 208, 48, 176, 112, 240, 8, 136, 72, 200,
			40, 168, 104, 232, 24, 152, 88, 216, 56, 184,
			120, 248, 4, 132, 68, 196, 36, 164, 100, 228,
			20, 148, 84, 212, 52, 180, 116, 244, 12, 140,
			76, 204, 44, 172, 108, 236, 28, 156, 92, 220,
			60, 188, 124, 252, 2, 130, 66, 194, 34, 162,
			98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
			10, 138, 74, 202, 42, 170, 106, 234, 26, 154,
			90, 218, 58, 186, 122, 250, 6, 134, 70, 198,
			38, 166, 102, 230, 22, 150, 86, 214, 54, 182,
			118, 246, 14, 142, 78, 206, 46, 174, 110, 238,
			30, 158, 94, 222, 62, 190, 126, 254, 1, 129,
			65, 193, 33, 161, 97, 225, 17, 145, 81, 209,
			49, 177, 113, 241, 9, 137, 73, 201, 41, 169,
			105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
			5, 133, 69, 197, 37, 165, 101, 229, 21, 149,
			85, 213, 53, 181, 117, 245, 13, 141, 77, 205,
			45, 173, 109, 237, 29, 157, 93, 221, 61, 189,
			125, 253, 3, 131, 67, 195, 35, 163, 99, 227,
			19, 147, 83, 211, 51, 179, 115, 243, 11, 139,
			75, 203, 43, 171, 107, 235, 27, 155, 91, 219,
			59, 187, 123, 251, 7, 135, 71, 199, 39, 167,
			103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
			15, 143, 79, 207, 47, 175, 111, 239, 31, 159,
			95, 223, 63, 191, 127, 255
		};

		private static readonly byte[] logTable = new byte[256]
		{
			255, 0, 1, 1, 2, 2, 2, 2, 3, 3,
			3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
			4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
			4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
			5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
			5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
			5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
			6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
			6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
			6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
			6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
			6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
			6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7
		};

		public int Count => count;

		public SplitOrderedList(IEqualityComparer<TKey> comparer)
		{
			this.comparer = comparer;
			head = new Node().Init(0uL);
			tail = new Node().Init(ulong.MaxValue);
			head.Next = tail;
			SetBucket(0u, head);
		}

		public T InsertOrUpdate(uint key, TKey subKey, Func<T> addGetter, Func<T, T> updateGetter)
		{
			if (InsertInternal(key, subKey, default(T), addGetter, out var current))
			{
				return current.Data;
			}
			return current.Data = updateGetter(current.Data);
		}

		public T InsertOrUpdate(uint key, TKey subKey, T addValue, T updateValue)
		{
			if (InsertInternal(key, subKey, addValue, null, out var current))
			{
				return current.Data;
			}
			return current.Data = updateValue;
		}

		public bool Insert(uint key, TKey subKey, T data)
		{
			Node current;
			return InsertInternal(key, subKey, data, null, out current);
		}

		public T InsertOrGet(uint key, TKey subKey, T data, Func<T> dataCreator)
		{
			InsertInternal(key, subKey, data, dataCreator, out var current);
			return current.Data;
		}

		private bool InsertInternal(uint key, TKey subKey, T data, Func<T> dataCreator, out Node current)
		{
			Node node = pool.Take().Init(ComputeRegularKey(key), subKey, data);
			uint num = key % (uint)size;
			Node startPoint;
			if ((startPoint = GetBucket(num)) == null)
			{
				startPoint = InitializeBucket(num);
			}
			if (!ListInsert(node, startPoint, out current, dataCreator))
			{
				return false;
			}
			int num2 = size;
			if (Interlocked.Increment(ref count) / num2 > 5 && (num2 & 0x40000000) == 0)
			{
				Interlocked.CompareExchange(ref size, 2 * num2, num2);
			}
			current = node;
			return true;
		}

		public bool Find(uint key, TKey subKey, out T data)
		{
			uint num = key % (uint)size;
			data = default(T);
			Node startPoint;
			if ((startPoint = GetBucket(num)) == null)
			{
				startPoint = InitializeBucket(num);
			}
			if (!ListFind(ComputeRegularKey(key), subKey, startPoint, out var data2))
			{
				return false;
			}
			data = data2.Data;
			return !data2.Marked;
		}

		public bool CompareExchange(uint key, TKey subKey, T data, Func<T, bool> check)
		{
			uint num = key % (uint)size;
			Node startPoint;
			if ((startPoint = GetBucket(num)) == null)
			{
				startPoint = InitializeBucket(num);
			}
			if (!ListFind(ComputeRegularKey(key), subKey, startPoint, out var data2))
			{
				return false;
			}
			if (!check(data2.Data))
			{
				return false;
			}
			data2.Data = data;
			return true;
		}

		public bool Delete(uint key, TKey subKey, out T data)
		{
			uint num = key % (uint)size;
			Node startPoint;
			if ((startPoint = GetBucket(num)) == null)
			{
				startPoint = InitializeBucket(num);
			}
			if (!ListDelete(startPoint, ComputeRegularKey(key), subKey, out data))
			{
				return false;
			}
			Interlocked.Decrement(ref count);
			return true;
		}

		public IEnumerator<T> GetEnumerator()
		{
			for (Node node = head.Next; node != tail; node = node.Next)
			{
				while (node.Marked || (node.Key & 1) == 0)
				{
					node = node.Next;
					if (node == tail)
					{
						yield break;
					}
				}
				yield return node.Data;
			}
		}

		private Node InitializeBucket(uint b)
		{
			uint parent = GetParent(b);
			Node startPoint;
			if ((startPoint = GetBucket(parent)) == null)
			{
				startPoint = InitializeBucket(parent);
			}
			Node node = pool.Take().Init(ComputeDummyKey(b));
			if (!ListInsert(node, startPoint, out var current, null))
			{
				return current;
			}
			return SetBucket(b, node);
		}

		private static uint GetParent(uint v)
		{
			uint num;
			uint num2;
			int num3 = (((num = v >> 16) == 0) ? (((num2 = v >> 8) != 0) ? (8 + logTable[num2]) : logTable[v]) : (((num2 = num >> 8) != 0) ? (24 + logTable[num2]) : (16 + logTable[num])));
			return (uint)(v & ~(1 << num3));
		}

		private static ulong ComputeRegularKey(uint key)
		{
			return ComputeDummyKey(key) | 1;
		}

		private static ulong ComputeDummyKey(uint key)
		{
			return (ulong)(uint)((reverseTable[key & 0xFF] << 24) | (reverseTable[(key >> 8) & 0xFF] << 16) | (reverseTable[(key >> 16) & 0xFF] << 8) | reverseTable[(key >> 24) & 0xFF]) << 1;
		}

		private Node GetBucket(uint index)
		{
			if (index >= buckets.Length)
			{
				return null;
			}
			return buckets[index];
		}

		private Node SetBucket(uint index, Node node)
		{
			try
			{
				slim.EnterReadLock();
				CheckSegment(index, readLockTaken: true);
				Interlocked.CompareExchange(ref buckets[index], node, null);
				return buckets[index];
			}
			finally
			{
				slim.ExitReadLock();
			}
		}

		private void CheckSegment(uint segment, bool readLockTaken)
		{
			if (segment < buckets.Length)
			{
				return;
			}
			if (readLockTaken)
			{
				slim.ExitReadLock();
			}
			try
			{
				slim.EnterWriteLock();
				while (segment >= buckets.Length)
				{
					Array.Resize(ref buckets, buckets.Length * 2);
				}
			}
			finally
			{
				slim.ExitWriteLock();
			}
			if (readLockTaken)
			{
				slim.EnterReadLock();
			}
		}

		private Node ListSearch(ulong key, TKey subKey, ref Node left, Node h)
		{
			Node node = null;
			Node node2 = null;
			while (true)
			{
				Node node3 = h;
				Node next = node3.Next;
				do
				{
					if (!next.Marked)
					{
						left = node3;
						node = next;
					}
					node3 = (next.Marked ? next.Next : next);
					if (node3 == tail)
					{
						break;
					}
					next = node3.Next;
				}
				while (next.Marked || node3.Key < key || (next.Key == key && !comparer.Equals(subKey, node3.SubKey)));
				node2 = node3;
				if (node == node2)
				{
					if (node2 == tail || !node2.Next.Marked)
					{
						return node2;
					}
				}
				else if (Interlocked.CompareExchange(ref left.Next, node2, node) == node)
				{
					pool.Release(node);
					if (node2 == tail || !node2.Next.Marked)
					{
						break;
					}
				}
			}
			return node2;
		}

		private bool ListDelete(Node startPoint, ulong key, TKey subKey, out T data)
		{
			Node node = null;
			Node node2 = null;
			Node left = null;
			data = default(T);
			Node node3 = null;
			while (true)
			{
				node = ListSearch(key, subKey, ref left, startPoint);
				if (node == tail || node.Key != key || !comparer.Equals(subKey, node.SubKey))
				{
					return false;
				}
				data = node.Data;
				node2 = node.Next;
				if (!node2.Marked)
				{
					if (node3 == null)
					{
						node3 = pool.Take();
					}
					node3.Init(node2);
					if (Interlocked.CompareExchange(ref node.Next, node3, node2) == node2)
					{
						break;
					}
				}
			}
			if (Interlocked.CompareExchange(ref left.Next, node2, node) != node)
			{
				ListSearch(node.Key, subKey, ref left, startPoint);
			}
			else
			{
				pool.Release(node);
			}
			return true;
		}

		private bool ListInsert(Node newNode, Node startPoint, out Node current, Func<T> dataCreator)
		{
			ulong key = newNode.Key;
			Node node = null;
			Node left = null;
			do
			{
				node = (current = ListSearch(key, newNode.SubKey, ref left, startPoint));
				if (node != tail && node.Key == key && comparer.Equals(newNode.SubKey, node.SubKey))
				{
					return false;
				}
				newNode.Next = node;
				if (dataCreator != null)
				{
					newNode.Data = dataCreator();
				}
			}
			while (Interlocked.CompareExchange(ref left.Next, newNode, node) != node);
			return true;
		}

		private bool ListFind(ulong key, TKey subKey, Node startPoint, out Node data)
		{
			Node node = null;
			Node left = null;
			data = null;
			node = (data = ListSearch(key, subKey, ref left, startPoint));
			if (node != tail && node.Key == key)
			{
				return comparer.Equals(subKey, node.SubKey);
			}
			return false;
		}
	}
	internal abstract class ObjectPool<T> where T : class
	{
		private const int capacity = 20;

		private const int bit = 134217728;

		private readonly T[] buffer;

		private int addIndex;

		private int removeIndex;

		public ObjectPool()
		{
			buffer = new T[20];
			for (int i = 0; i < 20; i++)
			{
				buffer[i] = Creator();
			}
			addIndex = 19;
		}

		protected abstract T Creator();

		public T Take()
		{
			if ((addIndex & -134217729) - 1 == removeIndex)
			{
				return Creator();
			}
			int num = 3;
			int num2;
			T result;
			do
			{
				num2 = removeIndex;
				if ((addIndex & -134217729) - 1 == num2 || num == 0)
				{
					return Creator();
				}
				result = buffer[num2 % 20];
			}
			while (Interlocked.CompareExchange(ref removeIndex, num2 + 1, num2) != num2 && --num > -1);
			return result;
		}

		public void Release(T obj)
		{
			if (obj == null || addIndex - removeIndex >= 19)
			{
				return;
			}
			int num = 3;
			int num2;
			while (true)
			{
				num2 = addIndex;
				if ((num2 & 0x8000000) <= 0)
				{
					if (num2 - removeIndex >= 19)
					{
						return;
					}
					if (Interlocked.CompareExchange(ref addIndex, num2 + 1 + 134217728, num2) == num2 || --num <= 0)
					{
						break;
					}
				}
			}
			buffer[num2 % 20] = obj;
			addIndex -= 134217728;
		}
	}
	public static class Partitioner
	{
		public static OrderablePartitioner<TSource> Create<TSource>(IEnumerable<TSource> source)
		{
			if (source is IList<TSource> list)
			{
				return Create(list, loadBalance: true);
			}
			return new EnumerablePartitioner<TSource>(source);
		}

		public static OrderablePartitioner<TSource> Create<TSource>(TSource[] array, bool loadBalance)
		{
			return Create((IList<TSource>)array, loadBalance);
		}

		public static OrderablePartitioner<TSource> Create<TSource>(IList<TSource> list, bool loadBalance)
		{
			return new ListPartitioner<TSource>(list);
		}

		public static OrderablePartitioner<Tuple<int, int>> Create(int fromInclusive, int toExclusive)
		{
			int num = (toExclusive - fromInclusive) / (Environment.ProcessorCount * 3);
			if (num < 1)
			{
				num = 1;
			}
			return Create(fromInclusive, toExclusive, num);
		}

		public static OrderablePartitioner<Tuple<int, int>> Create(int fromInclusive, int toExclusive, int rangeSize)
		{
			if (fromInclusive >= toExclusive)
			{
				throw new ArgumentOutOfRangeException("toExclusive");
			}
			if (rangeSize <= 0)
			{
				throw new ArgumentOutOfRangeException("rangeSize");
			}
			return new UserRangePartitioner(fromInclusive, toExclusive, rangeSize);
		}

		public static OrderablePartitioner<Tuple<long, long>> Create(long fromInclusive, long toExclusive)
		{
			long num = (toExclusive - fromInclusive) / (Environment.ProcessorCount * 3);
			if (num < 1)
			{
				num = 1L;
			}
			return Create(fromInclusive, toExclusive, num);
		}

		public static OrderablePartitioner<Tuple<long, long>> Create(long fromInclusive, long toExclusive, long rangeSize)
		{
			if (rangeSize <= 0)
			{
				throw new ArgumentOutOfRangeException("rangeSize");
			}
			if (fromInclusive >= toExclusive)
			{
				throw new ArgumentOutOfRangeException("toExclusive");
			}
			return new UserLongRangePartitioner(fromInclusive, toExclusive, rangeSize);
		}
	}
	public abstract class Partitioner<TSource>
	{
		public virtual bool SupportsDynamicPartitions => false;

		public virtual IEnumerable<TSource> GetDynamicPartitions()
		{
			if (!SupportsDynamicPartitions)
			{
				throw new NotSupportedException();
			}
			return null;
		}

		public abstract IList<IEnumerator<TSource>> GetPartitions(int partitionCount);
	}
}
namespace System.Threading.Tasks
{
	internal class TaskConstants<T>
	{
		internal static readonly Task<T> Canceled;

		static TaskConstants()
		{
			TaskCompletionSource<T> taskCompletionSource = new TaskCompletionSource<T>();
			taskCompletionSource.SetCanceled();
			Canceled = taskCompletionSource.Task;
		}
	}
}
namespace System
{
	[Serializable]
	[ComVisible(true)]
	public class OperationCanceledException : SystemException
	{
		private const int Result = -2146233029;

		private CancellationToken? token;

		public CancellationToken CancellationToken
		{
			get
			{
				if (!token.HasValue)
				{
					return CancellationToken.None;
				}
				return token.Value;
			}
		}

		public OperationCanceledException()
			: base("The operation was canceled.")
		{
			base.HResult = -2146233029;
		}

		public OperationCanceledException(string message)
			: base(message)
		{
			base.HResult = -2146233029;
		}

		public OperationCanceledException(string message, Exception innerException)
			: base(message, innerException)
		{
			base.HResult = -2146233029;
		}

		protected OperationCanceledException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		public OperationCanceledException(CancellationToken token)
			: this()
		{
			this.token = token;
		}

		public OperationCanceledException(string message, CancellationToken token)
			: this(message)
		{
			this.token = token;
		}

		public OperationCanceledException(string message, Exception innerException, CancellationToken token)
			: base(message, innerException)
		{
			this.token = token;
		}
	}
}
namespace System.Collections
{
	[Serializable]
	[ComVisible(true)]
	public sealed class Comparer : IComparer
	{
		public static readonly Comparer Default = new Comparer();

		public static readonly Comparer DefaultInvariant = new Comparer(CultureInfo.InvariantCulture);

		private CompareInfo m_compareInfo;

		private Comparer()
		{
		}

		public Comparer(CultureInfo culture)
		{
			if (culture == null)
			{
				throw new ArgumentNullException("culture");
			}
			m_compareInfo = culture.CompareInfo;
		}

		public int Compare(object a, object b)
		{
			if (a == b)
			{
				return 0;
			}
			if (a == null)
			{
				return -1;
			}
			if (b == null)
			{
				return 1;
			}
			if (m_compareInfo != null)
			{
				string text = a as string;
				string text2 = b as string;
				if (text != null && text2 != null)
				{
					return m_compareInfo.Compare(text, text2);
				}
			}
			if (a is IComparable)
			{
				return (a as IComparable).CompareTo(b);
			}
			if (b is IComparable)
			{
				return -(b as IComparable).CompareTo(a);
			}
			throw new ArgumentException("Neither 'a' nor 'b' implements IComparable.");
		}
	}
}
namespace System.Threading
{
	public struct CancellationTokenRegistration : IDisposable, IEquatable<CancellationTokenRegistration>
	{
		private int id;

		private CancellationTokenSource source;

		internal CancellationTokenRegistration(int id, CancellationTokenSource source)
		{
			this.id = id;
			this.source = source;
		}

		public void Dispose()
		{
			source.RemoveCallback(this);
		}

		public bool Equals(CancellationTokenRegistration other)
		{
			if (id == other.id)
			{
				return source == other.source;
			}
			return false;
		}

		public static bool operator ==(CancellationTokenRegistration left, CancellationTokenRegistration right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(CancellationTokenRegistration left, CancellationTokenRegistration right)
		{
			return !left.Equals(right);
		}

		public override int GetHashCode()
		{
			return id.GetHashCode() ^ source.GetHashCode();
		}

		public override bool Equals(object obj)
		{
			if (!(obj is CancellationTokenRegistration))
			{
				return false;
			}
			return Equals((CancellationTokenRegistration)obj);
		}
	}
}
namespace System.Collections.Concurrent
{
	public abstract class OrderablePartitioner<TSource> : Partitioner<TSource>
	{
		private class ProxyEnumerator : IEnumerator<TSource>, IEnumerator, IDisposable
		{
			private IEnumerator<KeyValuePair<long, TSource>> internalEnumerator;

			object IEnumerator.Current => Current;

			public TSource Current { get; private set; }

			internal ProxyEnumerator(IEnumerator<KeyValuePair<long, TSource>> enumerator)
			{
				internalEnumerator = enumerator;
			}

			public void Dispose()
			{
				internalEnumerator.Dispose();
			}

			public bool MoveNext()
			{
				if (!internalEnumerator.MoveNext())
				{
					return false;
				}
				Current = internalEnumerator.Current.Value;
				return true;
			}

			public void Reset()
			{
				internalEnumerator.Reset();
			}
		}

		private bool keysOrderedInEachPartition;

		private bool keysOrderedAcrossPartitions;

		private bool keysNormalized;

		public bool KeysOrderedInEachPartition => keysOrderedInEachPartition;

		public bool KeysOrderedAcrossPartitions => keysOrderedAcrossPartitions;

		public bool KeysNormalized => keysNormalized;

		protected OrderablePartitioner(bool keysOrderedInEachPartition, bool keysOrderedAcrossPartitions, bool keysNormalized)
		{
			this.keysOrderedInEachPartition = keysOrderedInEachPartition;
			this.keysOrderedAcrossPartitions = keysOrderedAcrossPartitions;
			this.keysNormalized = keysNormalized;
		}

		public override IEnumerable<TSource> GetDynamicPartitions()
		{
			foreach (KeyValuePair<long, TSource> item in GetOrderableDynamicPartitions())
			{
				KeyValuePair<long, TSource> keyValuePair = item;
				yield return keyValuePair.Value;
			}
		}

		public override IList<IEnumerator<TSource>> GetPartitions(int partitionCount)
		{
			IEnumerator<TSource>[] array = new IEnumerator<TSource>[partitionCount];
			IList<IEnumerator<KeyValuePair<long, TSource>>> orderablePartitions = GetOrderablePartitions(partitionCount);
			for (int i = 0; i < orderablePartitions.Count; i++)
			{
				array[i] = new ProxyEnumerator(orderablePartitions[i]);
			}
			return array;
		}

		private IEnumerator<TSource> GetProxyEnumerator(IEnumerator<KeyValuePair<long, TSource>> enumerator)
		{
			while (enumerator.MoveNext())
			{
				yield return enumerator.Current.Value;
			}
		}

		public abstract IList<IEnumerator<KeyValuePair<long, TSource>>> GetOrderablePartitions(int partitionCount);

		public virtual IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions()
		{
			if (!SupportsDynamicPartitions)
			{
				throw new NotSupportedException();
			}
			return null;
		}
	}
}
namespace System.Collections.Concurrent.Partitioners
{
	internal class UserRangePartitioner : OrderablePartitioner<Tuple<int, int>>
	{
		private readonly int start;

		private readonly int end;

		private readonly int rangeSize;

		public UserRangePartitioner(int start, int end, int rangeSize)
			: base(keysOrderedInEachPartition: true, keysOrderedAcrossPartitions: true, keysNormalized: true)
		{
			this.start = start;
			this.end = end;
			this.rangeSize = rangeSize;
		}

		public override IList<IEnumerator<KeyValuePair<long, Tuple<int, int>>>> GetOrderablePartitions(int partitionCount)
		{
			if (partitionCount <= 0)
			{
				throw new ArgumentOutOfRangeException("partitionCount");
			}
			int currentIndex = 0;
			Func<int> getNextIndex = () => Interlocked.Increment(ref currentIndex) - 1;
			IEnumerator<KeyValuePair<long, Tuple<int, int>>>[] array = new IEnumerator<KeyValuePair<long, Tuple<int, int>>>[partitionCount];
			for (int i = 0; i < partitionCount; i++)
			{
				array[i] = GetEnumerator(getNextIndex);
			}
			return array;
		}

		private IEnumerator<KeyValuePair<long, Tuple<int, int>>> GetEnumerator(Func<int> getNextIndex)
		{
			while (true)
			{
				int index = getNextIndex();
				int sliceStart = index * rangeSize + start;
				if (sliceStart < end)
				{
					yield return new KeyValuePair<long, Tuple<int, int>>(index, Tuple.Create(sliceStart, Math.Min(end, sliceStart + rangeSize)));
					_ = sliceStart + rangeSize;
					continue;
				}
				break;
			}
		}
	}
	internal class UserLongRangePartitioner : OrderablePartitioner<Tuple<long, long>>
	{
		private readonly long start;

		private readonly long end;

		private readonly long rangeSize;

		public UserLongRangePartitioner(long start, long end, long rangeSize)
			: base(keysOrderedInEachPartition: true, keysOrderedAcrossPartitions: true, keysNormalized: true)
		{
			this.start = start;
			this.end = end;
			this.rangeSize = rangeSize;
		}

		public override IList<IEnumerator<KeyValuePair<long, Tuple<long, long>>>> GetOrderablePartitions(int partitionCount)
		{
			if (partitionCount <= 0)
			{
				throw new ArgumentOutOfRangeException("partitionCount");
			}
			long currentIndex = 0L;
			Func<long> getNextIndex = () => Interlocked.Increment(ref currentIndex) - 1;
			IEnumerator<KeyValuePair<long, Tuple<long, long>>>[] array = new IEnumerator<KeyValuePair<long, Tuple<long, long>>>[partitionCount];
			for (int i = 0; i < partitionCount; i++)
			{
				array[i] = GetEnumerator(getNextIndex);
			}
			return array;
		}

		private IEnumerator<KeyValuePair<long, Tuple<long, long>>> GetEnumerator(Func<long> getNextIndex)
		{
			while (true)
			{
				long index = getNextIndex();
				long sliceStart = index * rangeSize + start;
				if (sliceStart < end)
				{
					yield return new KeyValuePair<long, Tuple<long, long>>(index, Tuple.Create(sliceStart, Math.Min(end, sliceStart + rangeSize)));
					_ = sliceStart + rangeSize;
					continue;
				}
				break;
			}
		}
	}
}
namespace System
{
	public static class Tuple
	{
		public static Tuple<T1, T2, T3, T4, T5, T6, T7, Tuple<T8>> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8)
		{
			return new Tuple<T1, T2, T3, T4, T5, T6, T7, Tuple<T8>>(item1, item2, item3, item4, item5, item6, item7, new Tuple<T8>(item8));
		}

		public static Tuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7)
		{
			return new Tuple<T1, T2, T3, T4, T5, T6, T7>(item1, item2, item3, item4, item5, item6, item7);
		}

		public static Tuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
		{
			return new Tuple<T1, T2, T3, T4, T5, T6>(item1, item2, item3, item4, item5, item6);
		}

		public static Tuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
		{
			return new Tuple<T1, T2, T3, T4, T5>(item1, item2, item3, item4, item5);
		}

		public static Tuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 item1, T2 item2, T3 item3, T4 item4)
		{
			return new Tuple<T1, T2, T3, T4>(item1, item2, item3, item4);
		}

		public static Tuple<T1, T2, T3> Create<T1, T2, T3>(T1 item1, T2 item2, T3 item3)
		{
			return new Tuple<T1, T2, T3>(item1, item2, item3);
		}

		public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
		{
			return new Tuple<T1, T2>(item1, item2);
		}

		public static Tuple<T1> Create<T1>(T1 item1)
		{
			return new Tuple<T1>(item1);
		}
	}
}
namespace System.Threading.Tasks
{
	[DebuggerDisplay("Id = {Id}, Status = {Status}")]
	[DebuggerTypeProxy(typeof(TaskDebuggerView))]
	public class Task : IDisposable, IAsyncResult
	{
		internal const TaskCreationOptions WorkerTaskNotSupportedOptions = TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning;

		private const TaskCreationOptions MaxTaskCreationOptions = TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent | TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler;

		[ThreadStatic]
		private static Task current;

		[ThreadStatic]
		private static Action<Task> childWorkAdder;

		internal readonly Task parent;

		private readonly Task contAncestor;

		private static int id = -1;

		private static readonly TaskFactory defaultFactory = new TaskFactory();

		private CountdownEvent childTasks;

		private int taskId;

		private TaskCreationOptions taskCreationOptions;

		internal TaskScheduler scheduler;

		private TaskExceptionSlot exSlot;

		private TaskStatus status;

		private TaskActionInvoker invoker;

		private object state;

		internal AtomicBooleanValue executing;

		private TaskCompletionQueue<IContinuation> continuations;

		private CancellationToken token;

		private CancellationTokenRegistration? cancellationRegistration;

		public static TaskFactory Factory => defaultFactory;

		public static int? CurrentId => current?.Id;

		public AggregateException Exception
		{
			get
			{
				if (exSlot == null)
				{
					return null;
				}
				exSlot.Observed = true;
				return exSlot.Exception;
			}
		}

		public bool IsCanceled => status == TaskStatus.Canceled;

		public bool IsCompleted => status >= TaskStatus.RanToCompletion;

		public bool IsFaulted => status == TaskStatus.Faulted;

		public TaskCreationOptions CreationOptions => taskCreationOptions & (TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent | TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler);

		public TaskStatus Status
		{
			get
			{
				return status;
			}
			internal set
			{
				status = value;
				Thread.MemoryBarrier();
			}
		}

		private TaskExceptionSlot ExceptionSlot
		{
			get
			{
				if (exSlot != null)
				{
					return exSlot;
				}
				Interlocked.CompareExchange(ref exSlot, new TaskExceptionSlot(this), null);
				return exSlot;
			}
		}

		public object AsyncState => state;

		bool IAsyncResult.CompletedSynchronously => true;

		WaitHandle IAsyncResult.AsyncWaitHandle => null;

		public int Id => taskId;

		private bool IsContinuation => contAncestor != null;

		internal Task ContinuationAncestor => contAncestor;

		internal string DisplayActionMethod
		{
			get
			{
				Delegate action = invoker.Action;
				if ((object)action != null)
				{
					return action.Method.ToString();
				}
				return "<none>";
			}
		}

		internal Task Parent => parent;

		public Task(Action action)
			: this(action, TaskCreationOptions.None)
		{
		}

		public Task(Action action, TaskCreationOptions creationOptions)
			: this(action, CancellationToken.None, creationOptions)
		{
		}

		public Task(Action action, CancellationToken cancellationToken)
			: this(action, cancellationToken, TaskCreationOptions.None)
		{
		}

		public Task(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
			: this(TaskActionInvoker.Create(action), null, cancellationToken, creationOptions, current)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			if (creationOptions > (TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent | TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler) || creationOptions < TaskCreationOptions.None)
			{
				throw new ArgumentOutOfRangeException("creationOptions");
			}
		}

		public Task(Action<object> action, object state)
			: this(action, state, TaskCreationOptions.None)
		{
		}

		public Task(Action<object> action, object state, TaskCreationOptions creationOptions)
			: this(action, state, CancellationToken.None, creationOptions)
		{
		}

		public Task(Action<object> action, object state, CancellationToken cancellationToken)
			: this(action, state, cancellationToken, TaskCreationOptions.None)
		{
		}

		public Task(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
			: this(TaskActionInvoker.Create(action), state, cancellationToken, creationOptions, current)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			if (creationOptions > (TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent | TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler) || creationOptions < TaskCreationOptions.None)
			{
				throw new ArgumentOutOfRangeException("creationOptions");
			}
		}

		internal Task(TaskActionInvoker invoker, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, Task parent, Task contAncestor = null)
		{
			this.invoker = invoker;
			taskCreationOptions = creationOptions;
			this.state = state;
			taskId = Interlocked.Increment(ref id);
			status = (cancellationToken.IsCancellationRequested ? TaskStatus.Canceled : TaskStatus.Created);
			token = cancellationToken;
			this.parent = parent;
			this.contAncestor = contAncestor;
			if (CheckTaskOptions(taskCreationOptions, TaskCreationOptions.AttachedToParent))
			{
				parent?.AddChild();
			}
			if (token.CanBeCanceled)
			{
				cancellationRegistration = token.Register(delegate(object l)
				{
					((Task)l).CancelReal();
				}, this);
			}
		}

		private static bool CheckTaskOptions(TaskCreationOptions opt, TaskCreationOptions member)
		{
			return (opt & member) == member;
		}

		public void Start()
		{
			Start(TaskScheduler.Current);
		}

		public void Start(TaskScheduler scheduler)
		{
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			if (status >= TaskStatus.WaitingToRun)
			{
				throw new InvalidOperationException("The Task is not in a valid state to be started.");
			}
			if (IsContinuation)
			{
				throw new InvalidOperationException("Start may not be called on a continuation task");
			}
			SetupScheduler(scheduler);
			Schedule();
		}

		internal void SetupScheduler(TaskScheduler scheduler)
		{
			this.scheduler = scheduler;
			Status = TaskStatus.WaitingForActivation;
		}

		public void RunSynchronously()
		{
			RunSynchronously(TaskScheduler.Current);
		}

		public void RunSynchronously(TaskScheduler scheduler)
		{
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			if (Status > TaskStatus.WaitingForActivation)
			{
				throw new InvalidOperationException("The task is not in a valid state to be started");
			}
			SetupScheduler(scheduler);
			TaskStatus taskStatus = status;
			Status = TaskStatus.WaitingToRun;
			try
			{
				if (scheduler.RunInline(this))
				{
					return;
				}
			}
			catch (Exception innerException)
			{
				throw new TaskSchedulerException(innerException);
			}
			Status = taskStatus;
			Start(scheduler);
			Wait();
		}

		public Task ContinueWith(Action<Task> continuationAction)
		{
			return ContinueWith(continuationAction, TaskContinuationOptions.None);
		}

		public Task ContinueWith(Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
		{
			return ContinueWith(continuationAction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
		}

		public Task ContinueWith(Action<Task> continuationAction, CancellationToken cancellationToken)
		{
			return ContinueWith(continuationAction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
		}

		public Task ContinueWith(Action<Task> continuationAction, TaskScheduler scheduler)
		{
			return ContinueWith(continuationAction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
		}

		public Task ContinueWith(Action<Task> continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
		{
			if (continuationAction == null)
			{
				throw new ArgumentNullException("continuationAction");
			}
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			return ContinueWith(TaskActionInvoker.Create(continuationAction), cancellationToken, continuationOptions, scheduler);
		}

		internal Task ContinueWith(TaskActionInvoker invoker, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
		{
			Task task = new Task(invoker, null, cancellationToken, GetCreationOptions(continuationOptions), parent, this);
			ContinueWithCore(task, continuationOptions, scheduler);
			return task;
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction)
		{
			return ContinueWith(continuationFunction, TaskContinuationOptions.None);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
		{
			return ContinueWith(continuationFunction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
		{
			return ContinueWith(continuationFunction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskScheduler scheduler)
		{
			return ContinueWith(continuationFunction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
		{
			if (continuationFunction == null)
			{
				throw new ArgumentNullException("continuationFunction");
			}
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			return ContinueWith<TResult>(TaskActionInvoker.Create(continuationFunction), cancellationToken, continuationOptions, scheduler);
		}

		internal Task<TResult> ContinueWith<TResult>(TaskActionInvoker invoker, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
		{
			Task<TResult> task = new Task<TResult>(invoker, null, cancellationToken, GetCreationOptions(continuationOptions), parent, this);
			ContinueWithCore(task, continuationOptions, scheduler);
			return task;
		}

		internal void ContinueWithCore(Task continuation, TaskContinuationOptions options, TaskScheduler scheduler)
		{
			if ((options & (TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion)) == (TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion) || (options & (TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion)) == (TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion) || (options & (TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion)) == (TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion))
			{
				throw new ArgumentException("continuationOptions", "Some options are mutually exclusive");
			}
			continuation.scheduler = scheduler;
			continuation.Status = TaskStatus.WaitingForActivation;
			ContinueWith(new System.Threading.Tasks.TaskContinuation(continuation, options));
		}

		internal void ContinueWith(IContinuation continuation)
		{
			if (IsCompleted)
			{
				continuation.Execute();
				return;
			}
			continuations.Add(continuation);
			if (IsCompleted && continuations.Remove(continuation))
			{
				continuation.Execute();
			}
		}

		private void RemoveContinuation(IContinuation continuation)
		{
			continuations.Remove(continuation);
		}

		internal static TaskCreationOptions GetCreationOptions(TaskContinuationOptions kind)
		{
			TaskCreationOptions taskCreationOptions = TaskCreationOptions.None;
			if ((kind & TaskContinuationOptions.AttachedToParent) > TaskContinuationOptions.None)
			{
				taskCreationOptions |= TaskCreationOptions.AttachedToParent;
			}
			if ((kind & TaskContinuationOptions.PreferFairness) > TaskContinuationOptions.None)
			{
				taskCreationOptions |= TaskCreationOptions.PreferFairness;
			}
			if ((kind & TaskContinuationOptions.LongRunning) > TaskContinuationOptions.None)
			{
				taskCreationOptions |= TaskCreationOptions.LongRunning;
			}
			return taskCreationOptions;
		}

		internal void Schedule()
		{
			Status = TaskStatus.WaitingToRun;
			if (scheduler != TaskScheduler.Current || childWorkAdder == null || CheckTaskOptions(taskCreationOptions, TaskCreationOptions.PreferFairness))
			{
				scheduler.QueueTask(this);
			}
			else
			{
				childWorkAdder(this);
			}
		}

		private void ThreadStart()
		{
			if (!executing.TryRelaxedSet())
			{
				return;
			}
			if (cancellationRegistration.HasValue)
			{
				cancellationRegistration.Value.Dispose();
				cancellationRegistration = null;
			}
			current = this;
			TaskScheduler.Current = scheduler;
			if (!token.IsCancellationRequested)
			{
				status = TaskStatus.Running;
				try
				{
					InnerInvoke();
				}
				catch (OperationCanceledException ex)
				{
					if (token != CancellationToken.None && ex.CancellationToken == token)
					{
						CancelReal();
					}
					else
					{
						HandleGenericException(ex);
					}
				}
				catch (Exception e)
				{
					HandleGenericException(e);
				}
			}
			else
			{
				CancelReal();
			}
			Finish();
		}

		internal bool TrySetCanceled()
		{
			if (IsCompleted)
			{
				return false;
			}
			if (!executing.TryRelaxedSet())
			{
				SpinWait spinWait = default(SpinWait);
				while (!IsCompleted)
				{
					spinWait.SpinOnce();
				}
				return false;
			}
			CancelReal();
			return true;
		}

		internal bool TrySetException(AggregateException aggregate)
		{
			if (IsCompleted)
			{
				return false;
			}
			if (!executing.TryRelaxedSet())
			{
				SpinWait spinWait = default(SpinWait);
				while (!IsCompleted)
				{
					spinWait.SpinOnce();
				}
				return false;
			}
			HandleGenericException(aggregate);
			return true;
		}

		internal void Execute(Action<Task> childAdder)
		{
			childWorkAdder = childAdder;
			Execute();
		}

		internal void Execute()
		{
			ThreadStart();
		}

		internal void AddChild()
		{
			if (childTasks == null)
			{
				Interlocked.CompareExchange(ref childTasks, new CountdownEvent(1), null);
			}
			childTasks.AddCount();
		}

		internal void ChildCompleted(AggregateException childEx)
		{
			if (childEx != null)
			{
				if (ExceptionSlot.ChildExceptions == null)
				{
					Interlocked.CompareExchange(ref ExceptionSlot.ChildExceptions, new ConcurrentQueue<AggregateException>(), null);
				}
				ExceptionSlot.ChildExceptions.Enqueue(childEx);
			}
			if (childTasks.Signal() && status == TaskStatus.WaitingForChildrenToComplete)
			{
				Status = TaskStatus.RanToCompletion;
				ProcessChildExceptions();
				ProcessCompleteDelegates();
				if (CheckTaskOptions(taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null)
				{
					parent.ChildCompleted(Exception);
				}
			}
		}

		private void InnerInvoke()
		{
			if (IsContinuation)
			{
				invoker.Invoke(contAncestor, state, this);
			}
			else
			{
				invoker.Invoke(this, state, this);
			}
		}

		internal void Finish()
		{
			if (childTasks != null)
			{
				childTasks.Signal();
			}
			if (status == TaskStatus.Running)
			{
				if (childTasks == null || childTasks.IsSet)
				{
					Status = TaskStatus.RanToCompletion;
				}
				else
				{
					Status = TaskStatus.WaitingForChildrenToComplete;
				}
			}
			if (status == TaskStatus.RanToCompletion)
			{
				ProcessCompleteDelegates();
			}
			current = null;
			TaskScheduler.Current = null;
			if (cancellationRegistration.HasValue)
			{
				cancellationRegistration.Value.Dispose();
			}
			if (CheckTaskOptions(taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null && status != TaskStatus.WaitingForChildrenToComplete)
			{
				parent.ChildCompleted(Exception);
			}
		}

		private void ProcessCompleteDelegates()
		{
			if (continuations.HasElements)
			{
				IContinuation continuation;
				while (continuations.TryGetNextCompletion(out continuation))
				{
					continuation.Execute();
				}
			}
		}

		private void ProcessChildExceptions()
		{
			if (exSlot != null && exSlot.ChildExceptions != null)
			{
				if (ExceptionSlot.Exception == null)
				{
					exSlot.Exception = new AggregateException();
				}
				AggregateException result;
				while (exSlot.ChildExceptions.TryDequeue(out result))
				{
					exSlot.Exception.AddChildException(result);
				}
			}
		}

		internal void CancelReal()
		{
			Status = TaskStatus.Canceled;
			ProcessCompleteDelegates();
		}

		private void HandleGenericException(Exception e)
		{
			HandleGenericException(new AggregateException(e));
		}

		private void HandleGenericException(AggregateException e)
		{
			ExceptionSlot.Exception = e;
			Thread.MemoryBarrier();
			Status = TaskStatus.Faulted;
			ProcessCompleteDelegates();
		}

		internal void WaitOnChildren()
		{
			if (Status == TaskStatus.WaitingForChildrenToComplete && childTasks != null)
			{
				childTasks.Wait();
			}
		}

		public void Wait()
		{
			Wait(-1, CancellationToken.None);
		}

		public void Wait(CancellationToken cancellationToken)
		{
			Wait(-1, cancellationToken);
		}

		public bool Wait(TimeSpan timeout)
		{
			return Wait(CheckTimeout(timeout), CancellationToken.None);
		}

		public bool Wait(int millisecondsTimeout)
		{
			return Wait(millisecondsTimeout, CancellationToken.None);
		}

		public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
		{
			if (millisecondsTimeout < -1)
			{
				throw new ArgumentOutOfRangeException("millisecondsTimeout");
			}
			bool flag = true;
			if (!IsCompleted)
			{
				if (Status == TaskStatus.WaitingToRun && millisecondsTimeout == -1 && scheduler != null)
				{
					Execute();
				}
				if (!IsCompleted)
				{
					ManualResetEventSlim manualResetEventSlim = new ManualResetEventSlim();
					ManualEventSlot continuation = new ManualEventSlot(manualResetEventSlim);
					try
					{
						ContinueWith(continuation);
						flag = manualResetEventSlim.Wait(millisecondsTimeout, cancellationToken);
					}
					finally
					{
						if (!flag)
						{
							RemoveContinuation(continuation);
						}
						manualResetEventSlim.Dispose();
					}
				}
			}
			if (IsCanceled)
			{
				throw new AggregateException(new TaskCanceledException(this));
			}
			AggregateException exception = Exception;
			if (exception != null)
			{
				throw exception;
			}
			if (childTasks != null)
			{
				childTasks.Wait();
			}
			return flag;
		}

		public static void WaitAll(params Task[] tasks)
		{
			WaitAll(tasks, -1, CancellationToken.None);
		}

		public static void WaitAll(Task[] tasks, CancellationToken cancellationToken)
		{
			WaitAll(tasks, -1, cancellationToken);
		}

		public static bool WaitAll(Task[] tasks, TimeSpan timeout)
		{
			return WaitAll(tasks, CheckTimeout(timeout), CancellationToken.None);
		}

		public static bool WaitAll(Task[] tasks, int millisecondsTimeout)
		{
			return WaitAll(tasks, millisecondsTimeout, CancellationToken.None);
		}

		public static bool WaitAll(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
		{
			if (tasks == null)
			{
				throw new ArgumentNullException("tasks");
			}
			bool flag = true;
			foreach (Task task in tasks)
			{
				if (task == null)
				{
					throw new ArgumentNullException("tasks", "the tasks argument contains a null element");
				}
				flag &= task.Status == TaskStatus.RanToCompletion;
			}
			if (!flag)
			{
				CountdownEvent countdownEvent = new CountdownEvent(tasks.Length);
				CountdownEventSlot continuation = new CountdownEventSlot(countdownEvent);
				try
				{
					foreach (Task task2 in tasks)
					{
						task2.ContinueWith(continuation);
					}
					flag = countdownEvent.Wait(millisecondsTimeout, cancellationToken);
				}
				finally
				{
					List<Exception> list = null;
					foreach (Task task3 in tasks)
					{
						if (flag)
						{
							if (task3.Status != TaskStatus.RanToCompletion)
							{
								if (list == null)
								{
									list = new List<Exception>();
								}
								if (task3.Exception != null)
								{
									list.AddRange(task3.Exception.InnerExceptions);
								}
								else
								{
									list.Add(new TaskCanceledException(task3));
								}
							}
						}
						else
						{
							task3.RemoveContinuation(continuation);
						}
					}
					countdownEvent.Dispose();
					if (list != null)
					{
						throw new AggregateException(list);
					}
				}
			}
			return flag;
		}

		public static int WaitAny(params Task[] tasks)
		{
			return WaitAny(tasks, -1, CancellationToken.None);
		}

		public static int WaitAny(Task[] tasks, TimeSpan timeout)
		{
			return WaitAny(tasks, CheckTimeout(timeout));
		}

		public static int WaitAny(Task[] tasks, int millisecondsTimeout)
		{
			return WaitAny(tasks, millisecondsTimeout, CancellationToken.None);
		}

		public static int WaitAny(Task[] tasks, CancellationToken cancellationToken)
		{
			return WaitAny(tasks, -1, cancellationToken);
		}

		public static int WaitAny(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
		{
			if (tasks == null)
			{
				throw new ArgumentNullException("tasks");
			}
			if (millisecondsTimeout < -1)
			{
				throw new ArgumentOutOfRangeException("millisecondsTimeout");
			}
			CheckForNullTasks(tasks);
			if (tasks.Length > 0)
			{
				ManualResetEventSlim manualResetEventSlim = new ManualResetEventSlim();
				ManualEventSlot continuation = new ManualEventSlot(manualResetEventSlim);
				bool flag = false;
				try
				{
					for (int i = 0; i < tasks.Length; i++)
					{
						Task task = tasks[i];
						if (task.IsCompleted)
						{
							return i;
						}
						task.ContinueWith(continuation);
					}
					if (!(flag = manualResetEventSlim.Wait(millisecondsTimeout, cancellationToken)))
					{
						return -1;
					}
				}
				finally
				{
					if (!flag)
					{
						foreach (Task task2 in tasks)
						{
							task2.RemoveContinuation(continuation);
						}
					}
					manualResetEventSlim.Dispose();
				}
			}
			int result = -1;
			for (int k = 0; k < tasks.Length; k++)
			{
				Task task3 = tasks[k];
				if (task3.IsCompleted)
				{
					result = k;
					break;
				}
			}
			return result;
		}

		private static int CheckTimeout(TimeSpan timeout)
		{
			try
			{
				return checked((int)timeout.TotalMilliseconds);
			}
			catch (OverflowException)
			{
				throw new ArgumentOutOfRangeException("timeout");
			}
		}

		private static void CheckForNullTasks(Task[] tasks)
		{
			foreach (Task task in tasks)
			{
				if (task == null)
				{
					throw new ArgumentNullException("tasks", "the tasks argument contains a null element");
				}
			}
		}

		public void Dispose()
		{
			Dispose(disposing: true);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (!IsCompleted)
			{
				throw new InvalidOperationException("A task may only be disposed if it is in a completion state");
			}
			if (disposing)
			{
				invoker = null;
				state = null;
				if (cancellationRegistration.HasValue)
				{
					cancellationRegistration.Value.Dispose();
				}
			}
		}

		public Task ContinueWith(Action<Task, object> continuationAction, object state)
		{
			return ContinueWith(continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
		}

		public Task ContinueWith(Action<Task, object> continuationAction, object state, CancellationToken cancellationToken)
		{
			return ContinueWith(continuationAction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
		}

		public Task ContinueWith(Action<Task, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
		{
			return ContinueWith(continuationAction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
		}

		public Task ContinueWith(Action<Task, object> continuationAction, object state, TaskScheduler scheduler)
		{
			return ContinueWith(continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
		}

		public Task ContinueWith(Action<Task, object> continuationAction, object state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
		{
			if (continuationAction == null)
			{
				throw new ArgumentNullException("continuationAction");
			}
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			Task task = new Task(TaskActionInvoker.Create(continuationAction), state, cancellationToken, GetCreationOptions(continuationOptions), parent, this);
			ContinueWithCore(task, continuationOptions, scheduler);
			return task;
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state)
		{
			return ContinueWith(continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskContinuationOptions continuationOptions)
		{
			return ContinueWith(continuationFunction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken)
		{
			return ContinueWith(continuationFunction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler)
		{
			return ContinueWith(continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
		{
			if (continuationFunction == null)
			{
				throw new ArgumentNullException("continuationFunction");
			}
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			Task<TResult> task = new Task<TResult>(TaskActionInvoker.Create(continuationFunction), state, cancellationToken, GetCreationOptions(continuationOptions), parent, this);
			ContinueWithCore(task, continuationOptions, scheduler);
			return task;
		}

		public static Task<TResult> FromResult<TResult>(TResult result)
		{
			TaskCompletionSource<TResult> taskCompletionSource = new TaskCompletionSource<TResult>();
			taskCompletionSource.SetResult(result);
			return taskCompletionSource.Task;
		}

		public static Task Run(Action action)
		{
			return Run(action, CancellationToken.None);
		}

		public static Task Run(Action action, CancellationToken cancellationToken)
		{
			if (cancellationToken.IsCancellationRequested)
			{
				return TaskConstants.Canceled;
			}
			Task task = new Task(action, cancellationToken, TaskCreationOptions.DenyChildAttach);
			task.Start();
			return task;
		}

		public static Task Run(Func<Task> function)
		{
			return Run(function, CancellationToken.None);
		}

		public static Task Run(Func<Task> function, CancellationToken cancellationToken)
		{
			if (cancellationToken.IsCancellationRequested)
			{
				return TaskConstants.Canceled;
			}
			Task<Task> task = new Task<Task>(function, cancellationToken);
			task.Start();
			return task;
		}

		public static Task<TResult> Run<TResult>(Func<TResult> function)
		{
			return Run(function, CancellationToken.None);
		}

		public static Task<TResult> Run<TResult>(Func<TResult> function, CancellationToken cancellationToken)
		{
			if (cancellationToken.IsCancellationRequested)
			{
				return TaskConstants<TResult>.Canceled;
			}
			Task<TResult> task = new Task<TResult>(function, cancellationToken, TaskCreationOptions.DenyChildAttach);
			task.Start();
			return task;
		}
	}
}
namespace System.Collections.Concurrent
{
	public interface IProducerConsumerCollection<T> : IEnumerable<T>, ICollection, IEnumerable
	{
		bool TryAdd(T item);

		bool TryTake(out T item);

		T[] ToArray();

		void CopyTo(T[] array, int index);
	}
	[DebuggerTypeProxy(typeof(CollectionDebuggerView<>))]
	[DebuggerDisplay("Count={Count}")]
	public class ConcurrentQueue<T> : IProducerConsumerCollection<T>, IEnumerable<T>, ICollection, IEnumerable
	{
		private class Node
		{
			public T Value;

			public Node Next;
		}

		private class NodeObjectPool : ObjectPool<Node>
		{
			protected override Node Creator()
			{
				return new Node();
			}
		}

		private Node head = new Node();

		private Node tail;

		private int count;

		private static readonly NodeObjectPool pool = new NodeObjectPool();

		private object syncRoot = new object();

		bool ICollection.IsSynchronized => true;

		object ICollection.SyncRoot => syncRoot;

		public int Count => count;

		public bool IsEmpty => count == 0;

		private static Node ZeroOut(Node node)
		{
			node.Value = default(T);
			node.Next = null;
			return node;
		}

		public ConcurrentQueue()
		{
			tail = head;
		}

		public ConcurrentQueue(IEnumerable<T> collection)
			: this()
		{
			foreach (T item in collection)
			{
				Enqueue(item);
			}
		}

		public void Enqueue(T item)
		{
			Node node = pool.Take();
			node.Value = item;
			Node node2 = null;
			Node node3 = null;
			bool flag = false;
			while (!flag)
			{
				node2 = tail;
				node3 = node2.Next;
				if (tail == node2)
				{
					if (node3 == null)
					{
						flag = Interlocked.CompareExchange(ref tail.Next, node, null) == null;
					}
					else
					{
						Interlocked.CompareExchange(ref tail, node3, node2);
					}
				}
			}
			Interlocked.CompareExchange(ref tail, node, node2);
			Interlocked.Increment(ref count);
		}

		bool IProducerConsumerCollection<T>.TryAdd(T item)
		{
			Enqueue(item);
			return true;
		}

		public bool TryDequeue(out T result)
		{
			result = default(T);
			bool flag = false;
			while (!flag)
			{
				Node node = head;
				Node node2 = tail;
				Node next = node.Next;
				if (node != head)
				{
					continue;
				}
				if (node == node2)
				{
					if (next != null)
					{
						Interlocked.CompareExchange(ref tail, next, node2);
					}
					result = default(T);
					return false;
				}
				result = next.Value;
				flag = Interlocked.CompareExchange(ref head, next, node) == node;
				if (flag)
				{
					pool.Release(ZeroOut(node));
				}
			}
			Interlocked.Decrement(ref count);
			return true;
		}

		public bool TryPeek(out T result)
		{
			if (IsEmpty)
			{
				result = default(T);
				return false;
			}
			Node next = head.Next;
			result = next.Value;
			return true;
		}

		internal void Clear()
		{
			count = 0;
			tail = (head = new Node());
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return InternalGetEnumerator();
		}

		public IEnumerator<T> GetEnumerator()
		{
			return InternalGetEnumerator();
		}

		private IEnumerator<T> InternalGetEnumerator()
		{
			Node my_head = head;
			while (true)
			{
				Node next;
				my_head = (next = my_head.Next);
				if (next != null)
				{
					yield return my_head.Value;
					continue;
				}
				break;
			}
		}

		void ICollection.CopyTo(Array array, int index)
		{
			if (array is T[] array2)
			{
				CopyTo(array2, index);
			}
		}

		public void CopyTo(T[] array, int index)
		{
			IEnumerator<T> enumerator = InternalGetEnumerator();
			int num = index;
			while (enumerator.MoveNext())
			{
				array[num++] = enumerator.Current;
			}
		}

		public T[] ToArray()
		{
			T[] array = new T[count];
			CopyTo(array, 0);
			return array;
		}

		bool IProducerConsumerCollection<T>.TryTake(out T item)
		{
			return TryDequeue(out item);
		}
	}
}
namespace System
{
	[Serializable]
	[DebuggerDisplay("Count = {InnerExceptions.Count}")]
	public class AggregateException : Exception
	{
		private const string defaultMessage = "One or more errors occured";

		private List<Exception> innerExceptions = new List<Exception>();

		public ReadOnlyCollection<Exception> InnerExceptions => innerExceptions.AsReadOnly();

		public AggregateException()
			: base("One or more errors occured")
		{
		}

		public AggregateException(string message)
			: base(message)
		{
		}

		public AggregateException(string message, Exception innerException)
			: base(message, innerException)
		{
			if (innerException == null)
			{
				throw new ArgumentNullException("innerException");
			}
			innerExceptions.Add(innerException);
		}

		protected AggregateException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		public AggregateException(params Exception[] innerExceptions)
			: this(string.Empty, innerExceptions)
		{
		}

		public AggregateException(string message, params Exception[] innerExceptions)
			: base(message, (innerExceptions == null || innerExceptions.Length == 0) ? null : innerExceptions[0])
		{
			if (innerExceptions == null)
			{
				throw new ArgumentNullException("innerExceptions");
			}
			foreach (Exception ex in innerExceptions)
			{
				if (ex == null)
				{
					throw new ArgumentException("One of the inner exception is null", "innerExceptions");
				}
			}
			this.innerExceptions.AddRange(innerExceptions);
		}

		public AggregateException(IEnumerable<Exception> innerExceptions)
			: this("One or more errors occured", innerExceptions)
		{
		}

		public AggregateException(string message, IEnumerable<Exception> innerExceptions)
			: this(message, new List<Exception>(innerExceptions).ToArray())
		{
		}

		public AggregateException Flatten()
		{
			List<Exception> list = new List<Exception>();
			foreach (Exception innerException in innerExceptions)
			{
				if (innerException is AggregateException ex)
				{
					list.AddRange(ex.Flatten().InnerExceptions);
				}
				else
				{
					list.Add(innerException);
				}
			}
			return new AggregateException(list);
		}

		public void Handle(Func<Exception, bool> predicate)
		{
			List<Exception> list = new List<Exception>();
			foreach (Exception innerException in innerExceptions)
			{
				try
				{
					if (!predicate(innerException))
					{
						list.Add(innerException);
					}
				}
				catch
				{
					throw new AggregateException(list);
				}
			}
			if (list.Count > 0)
			{
				throw new AggregateException(list);
			}
		}

		internal void AddChildException(AggregateException childEx)
		{
			if (innerExceptions == null)
			{
				innerExceptions = new List<Exception>();
			}
			if (childEx != null)
			{
				innerExceptions.Add(childEx);
			}
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder(base.ToString());
			int num = -1;
			foreach (Exception innerException in innerExceptions)
			{
				stringBuilder.Append(Environment.NewLine);
				stringBuilder.Append(" --> (Inner exception ");
				stringBuilder.Append(++num);
				stringBuilder.Append(") ");
				stringBuilder.Append(innerException.ToString());
				stringBuilder.Append(Environment.NewLine);
			}
			return stringBuilder.ToString();
		}

		public override void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			throw new NotImplementedException();
		}

		public override Exception GetBaseException()
		{
			if (innerExceptions == null || innerExceptions.Count == 0)
			{
				return this;
			}
			return innerExceptions[0].GetBaseException();
		}
	}
}
namespace System.Threading.Tasks
{
	internal class TaskExceptionSlot
	{
		public volatile AggregateException Exception;

		public volatile bool Observed;

		public ConcurrentQueue<AggregateException> ChildExceptions;

		private Task parent;

		public TaskExceptionSlot(Task parent)
		{
			this.parent = parent;
		}

		~TaskExceptionSlot()
		{
			if (Exception != null && (!Observed && !TaskScheduler.FireUnobservedEvent(parent, Exception).Observed))
			{
				parent = null;
				throw Exception;
			}
		}
	}
	internal abstract class TaskActionInvoker
	{
		private sealed class EmptyTaskActionInvoker : TaskActionInvoker
		{
			public override Delegate Action => null;

			public override void Invoke(Task owner, object state, Task context)
			{
			}
		}

		private sealed class ActionInvoke : TaskActionInvoker
		{
			private readonly Action action;

			public override Delegate Action => action;

			public ActionInvoke(Action action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action();
			}
		}

		private sealed class ActionObjectInvoke : TaskActionInvoker
		{
			private readonly Action<object> action;

			public override Delegate Action => action;

			public ActionObjectInvoke(Action<object> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action(state);
			}
		}

		private sealed class ActionTaskInvoke : TaskActionInvoker
		{
			private readonly Action<Task> action;

			public override Delegate Action => action;

			public ActionTaskInvoke(Action<Task> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action(owner);
			}
		}

		private sealed class ActionTasksInvoke : TaskActionInvoker
		{
			private readonly Action<Task[]> action;

			private readonly Task[] tasks;

			public override Delegate Action => action;

			public ActionTasksInvoke(Action<Task[]> action, Task[] tasks)
			{
				this.action = action;
				this.tasks = tasks;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action(tasks);
			}
		}

		private sealed class ActionTaskObjectInvoke : TaskActionInvoker
		{
			private readonly Action<Task, object> action;

			public override Delegate Action => action;

			public ActionTaskObjectInvoke(Action<Task, object> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action(owner, state);
			}
		}

		private sealed class ActionTaskObjectInvoke<TResult> : TaskActionInvoker
		{
			private readonly Action<Task<TResult>, object> action;

			public override Delegate Action => action;

			public ActionTaskObjectInvoke(Action<Task<TResult>, object> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action((Task<TResult>)owner, state);
			}
		}

		private sealed class ActionTaskInvoke<TResult> : TaskActionInvoker
		{
			private readonly Action<Task<TResult>> action;

			public override Delegate Action => action;

			public ActionTaskInvoke(Action<Task<TResult>> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action((Task<TResult>)owner);
			}
		}

		private sealed class ActionTaskSelected : TaskActionInvoker
		{
			private readonly Action<Task> action;

			private readonly Task[] tasks;

			public override Delegate Action => action;

			public ActionTaskSelected(Action<Task> action, Task[] tasks)
			{
				this.action = action;
				this.tasks = tasks;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				int result = ((Task<int>)owner).Result;
				action(tasks[result]);
			}
		}

		private sealed class FuncInvoke<TResult> : TaskActionInvoker
		{
			private readonly Func<TResult> action;

			public override Delegate Action => action;

			public FuncInvoke(Func<TResult> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TResult>)context).Result = action();
			}
		}

		private sealed class FuncTaskInvoke<TResult> : TaskActionInvoker
		{
			private readonly Func<Task, TResult> action;

			public override Delegate Action => action;

			public FuncTaskInvoke(Func<Task, TResult> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TResult>)context).Result = action(owner);
			}
		}

		private sealed class FuncTasksInvoke<TResult> : TaskActionInvoker
		{
			private readonly Func<Task[], TResult> action;

			private readonly Task[] tasks;

			public override Delegate Action => action;

			public FuncTasksInvoke(Func<Task[], TResult> action, Task[] tasks)
			{
				this.action = action;
				this.tasks = tasks;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TResult>)context).Result = action(tasks);
			}
		}

		private sealed class FuncTaskSelected<TResult> : TaskActionInvoker
		{
			private readonly Func<Task, TResult> action;

			private readonly Task[] tasks;

			public override Delegate Action => action;

			public FuncTaskSelected(Func<Task, TResult> action, Task[] tasks)
			{
				this.action = action;
				this.tasks = tasks;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				int result = ((Task<int>)owner).Result;
				((Task<TResult>)context).Result = action(tasks[result]);
			}
		}

		private sealed class FuncTaskInvoke<TResult, TNewResult> : TaskActionInvoker
		{
			private readonly Func<Task<TResult>, TNewResult> action;

			public override Delegate Action => action;

			public FuncTaskInvoke(Func<Task<TResult>, TNewResult> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TNewResult>)context).Result = action((Task<TResult>)owner);
			}
		}

		private sealed class FuncObjectInvoke<TResult> : TaskActionInvoker
		{
			private readonly Func<object, TResult> action;

			public override Delegate Action => action;

			public FuncObjectInvoke(Func<object, TResult> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TResult>)context).Result = action(state);
			}
		}

		private sealed class FuncTaskObjectInvoke<TResult> : TaskActionInvoker
		{
			private readonly Func<Task, object, TResult> action;

			public override Delegate Action => action;

			public FuncTaskObjectInvoke(Func<Task, object, TResult> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TResult>)context).Result = action(owner, state);
			}
		}

		private sealed class FuncTaskObjectInvoke<TResult, TNewResult> : TaskActionInvoker
		{
			private readonly Func<Task<TResult>, object, TNewResult> action;

			public override Delegate Action => action;

			public FuncTaskObjectInvoke(Func<Task<TResult>, object, TNewResult> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TNewResult>)context).Result = action((Task<TResult>)owner, state);
			}
		}

		public static readonly TaskActionInvoker Empty = new EmptyTaskActionInvoker();

		public abstract Delegate Action { get; }

		public static TaskActionInvoker Create(Action action)
		{
			return new ActionInvoke(action);
		}

		public static TaskActionInvoker Create(Action<object> action)
		{
			return new ActionObjectInvoke(action);
		}

		public static TaskActionInvoker Create(Action<Task> action)
		{
			return new ActionTaskInvoke(action);
		}

		public static TaskActionInvoker Create(Action<Task, object> action)
		{
			return new ActionTaskObjectInvoke(action);
		}

		public static TaskActionInvoker Create<TResult>(Action<Task<TResult>> action)
		{
			return new ActionTaskInvoke<TResult>(action);
		}

		public static TaskActionInvoker Create<TResult>(Action<Task<TResult>, object> action)
		{
			return new ActionTaskObjectInvoke<TResult>(action);
		}

		public static TaskActionInvoker Create<TResult>(Func<TResult> action)
		{
			return new FuncInvoke<TResult>(action);
		}

		public static TaskActionInvoker Create<TResult>(Func<object, TResult> action)
		{
			return new FuncObjectInvoke<TResult>(action);
		}

		public static TaskActionInvoker Create<TResult>(Func<Task, TResult> action)
		{
			return new FuncTaskInvoke<TResult>(action);
		}

		public static TaskActionInvoker Create<TResult>(Func<Task, object, TResult> action)
		{
			return new FuncTaskObjectInvoke<TResult>(action);
		}

		public static TaskActionInvoker Create<TResult, TNewResult>(Func<Task<TResult>, TNewResult> action)
		{
			return new FuncTaskInvoke<TResult, TNewResult>(action);
		}

		public static TaskActionInvoker Create<TResult, TNewResult>(Func<Task<TResult>, object, TNewResult> action)
		{
			return new FuncTaskObjectInvoke<TResult, TNewResult>(action);
		}

		public static TaskActionInvoker Create(Action<Task[]> action, Task[] tasks)
		{
			return new ActionTasksInvoke(action, tasks);
		}

		public static TaskActionInvoker Create<TResult>(Func<Task[], TResult> action, Task[] tasks)
		{
			return new FuncTasksInvoke<TResult>(action, tasks);
		}

		public static TaskActionInvoker Create(Action<Task> action, Task[] tasks)
		{
			return new ActionTaskSelected(action, tasks);
		}

		public static TaskActionInvoker Create<TResult>(Func<Task, TResult> action, Task[] tasks)
		{
			return new FuncTaskSelected<TResult>(action, tasks);
		}

		public abstract void Invoke(Task owner, object state, Task context);
	}
}
namespace System.Collections
{
	[Serializable]
	internal class ArrayList : IList, ICollection, IEnumerable
	{
		private sealed class ArrayListEnumerator : IEnumerator
		{
			private object m_Current;

			private ArrayList m_List;

			private int m_Pos;

			private int m_Index;

			private int m_Count;

			private int m_ExpectedStateChanges;

			public object Current
			{
				get
				{
					if (m_Pos == m_Index - 1)
					{
						throw new InvalidOperationException("Enumerator unusable (Reset pending, or past end of array.");
					}
					return m_Current;
				}
			}

			public ArrayListEnumerator(ArrayList list)
				: this(list, 0, list.Count)
			{
			}

			public object Clone()
			{
				return MemberwiseClone();
			}

			public ArrayListEnumerator(ArrayList list, int index, int count)
			{
				m_List = list;
				m_Index = index;
				m_Count = count;
				m_Pos = m_Index - 1;
				m_Current = null;
				m_ExpectedStateChanges = list._version;
			}

			public bool MoveNext()
			{
				if (m_List._version != m_ExpectedStateChanges)
				{
					throw new InvalidOperationException("List has changed.");
				}
				m_Pos++;
				if (m_Pos - m_Index < m_Count)
				{
					m_Current = m_List[m_Pos];
					return true;
				}
				return false;
			}

			public void Reset()
			{
				m_Current = null;
				m_Pos = m_Index - 1;
			}
		}

		private sealed class SimpleEnumerator : IEnumerator
		{
			private ArrayList list;

			private object currentElement;

			private int index;

			private int version;

			private static object endFlag = new object();

			public object Current
			{
				get
				{
					if (currentElement == endFlag)
					{
						if (index == -1)
						{
							throw new InvalidOperationException("Enumerator not started");
						}
						throw new InvalidOperationException("Enumerator ended");
					}
					return currentElement;
				}
			}

			public SimpleEnumerator(ArrayList list)
			{
				this.list = list;
				index = -1;
				version = list._version;
				currentElement = endFlag;
			}

			public object Clone()
			{
				return MemberwiseClone();
			}

			public bool MoveNext()
			{
				if (version != list._version)
				{
					throw new InvalidOperationException("List has changed.");
				}
				if (++index < list.Count)
				{
					currentElement = list[index];
					return true;
				}
				currentElement = endFlag;
				return false;
			}

			public void Reset()
			{
				if (version != list._version)
				{
					throw new InvalidOperationException("List has changed.");
				}
				currentElement = endFlag;
				index = -1;
			}
		}

		[Serializable]
		private sealed class ArrayListAdapter : ArrayList
		{
			private sealed class EnumeratorWithRange : IEnumerator
			{
				private int m_StartIndex;

				private int m_Count;

				private int m_MaxCount;

				private IEnumerator m_Enumerator;

				public object Current => m_Enumerator.Current;

				public EnumeratorWithRange(IEnumerator enumerator, int index, int count)
				{
					m_Count = 0;
					m_StartIndex = index;
					m_MaxCount = count;
					m_Enumerator = enumerator;
					Reset();
				}

				public object Clone()
				{
					return MemberwiseClone();
				}

				public bool MoveNext()
				{
					if (m_Count >= m_MaxCount)
					{
						return false;
					}
					m_Count++;
					return m_Enumerator.MoveNext();
				}

				public void Reset()
				{
					m_Count = 0;
					m_Enumerator.Reset();
					for (int i = 0; i < m_StartIndex; i++)
					{
						m_Enumerator.MoveNext();
					}
				}
			}

			private IList m_Adaptee;

			public override object this[int index]
			{
				get
				{
					return m_Adaptee[index];
				}
				set
				{
					m_Adaptee[index] = value;
				}
			}

			public override int Count => m_Adaptee.Count;

			public override int Capacity
			{
				get
				{
					return m_Adaptee.Count;
				}
				set
				{
					if (value < m_Adaptee.Count)
					{
						throw new ArgumentException("capacity");
					}
				}
			}

			public override bool IsFixedSize => m_Adaptee.IsFixedSize;

			public override bool IsReadOnly => m_Adaptee.IsReadOnly;

			public override object SyncRoot => m_Adaptee.SyncRoot;

			public override bool IsSynchronized => m_Adaptee.IsSynchronized;

			public ArrayListAdapter(IList adaptee)
				: base(0, forceZeroSize: true)
			{
				m_Adaptee = adaptee;
			}

			public override int Add(object value)
			{
				return m_Adaptee.Add(value);
			}

			public override void Clear()
			{
				m_Adaptee.Clear();
			}

			public override bool Contains(object value)
			{
				return m_Adaptee.Contains(value);
			}

			public override int IndexOf(object value)
			{
				return m_Adaptee.IndexOf(value);
			}

			public override int IndexOf(object value, int startIndex)
			{
				return IndexOf(value, startIndex, m_Adaptee.Count - startIndex);
			}

			public override int IndexOf(object value, int startIndex, int count)
			{
				if (startIndex < 0 || startIndex > m_Adaptee.Count)
				{
					ThrowNewArgumentOutOfRangeException("startIndex", startIndex, "Does not specify valid index.");
				}
				if (count < 0)
				{
					ThrowNewArgumentOutOfRangeException("count", count, "Can't be less than 0.");
				}
				if (startIndex > m_Adaptee.Count - count)
				{
					throw new ArgumentOutOfRangeException("count", "Start index and count do not specify a valid range.");
				}
				if (value == null)
				{
					for (int i = startIndex; i < startIndex + count; i++)
					{
						if (m_Adaptee[i] == null)
						{
							return i;
						}
					}
				}
				else
				{
					for (int j = startIndex; j < startIndex + count; j++)
					{
						if (value.Equals(m_Adaptee[j]))
						{
							return j;
						}
					}
				}
				return -1;
			}

			public override int LastIndexOf(object value)
			{
				return LastIndexOf(value, m_Adaptee.Count - 1);
			}

			public override int LastIndexOf(object value, int startIndex)
			{
				return LastIndexOf(value, startIndex, startIndex + 1);
			}

			public override int LastIndexOf(object value, int startIndex, int count)
			{
				if (startIndex < 0)
				{
					ThrowNewArgumentOutOfRangeException("startIndex", startIndex, "< 0");
				}
				if (count < 0)
				{
					ThrowNewArgumentOutOfRangeException("count", count, "count is negative.");
				}
				if (startIndex - count + 1 < 0)
				{
					ThrowNewArgumentOutOfRangeException("count", count, "count is too large.");
				}
				if (value == null)
				{
					for (int num = startIndex; num > startIndex - count; num--)
					{
						if (m_Adaptee[num] == null)
						{
							return num;
						}
					}
				}
				else
				{
					for (int num2 = startIndex; num2 > startIndex - count; num2--)
					{
						if (value.Equals(m_Adaptee[num2]))
						{
							return num2;
						}
					}
				}
				return -1;
			}

			public override void Insert(int index, object value)
			{
				m_Adaptee.Insert(index, value);
			}

			public override void InsertRange(int index, ICollection c)
			{
				if (c == null)
				{
					throw new ArgumentNullException("c");
				}
				if (index > m_Adaptee.Count)
				{
					ThrowNewArgumentOutOfRangeException("index", index, "Index must be >= 0 and <= Count.");
				}
				foreach (object item in c)
				{
					m_Adaptee.Insert(index++, item);
				}
			}

			public override void Remove(object value)
			{
				m_Adaptee.Remove(value);
			}

			public override void RemoveAt(int index)
			{
				m_Adaptee.RemoveAt(index);
			}

			public override void RemoveRange(int index, int count)
			{
				CheckRange(index, count, m_Adaptee.Count);
				for (int i = 0; i < count; i++)
				{
					m_Adaptee.RemoveAt(index);
				}
			}

			public override void Reverse()
			{
				Reverse(0, m_Adaptee.Count);
			}

			public override void Reverse(int index, int count)
			{
				CheckRange(index, count, m_Adaptee.Count);
				for (int i = 0; i < count / 2; i++)
				{
					object value = m_Adaptee[i + index];
					m_Adaptee[i + index] = m_Adaptee[index + count - i + index - 1];
					m_Adaptee[index + count - i + index - 1] = value;
				}
			}

			public override void SetRange(int index, ICollection c)
			{
				if (c == null)
				{
					throw new ArgumentNullException("c");
				}
				if (index < 0 || index + c.Count > m_Adaptee.Count)
				{
					throw new ArgumentOutOfRangeException("index");
				}
				int num = index;
				foreach (object item in c)
				{
					m_Adaptee[num++] = item;
				}
			}

			public override void CopyTo(Array array)
			{
				m_Adaptee.CopyTo(array, 0);
			}

			public override void CopyTo(Array array, int index)
			{
				m_Adaptee.CopyTo(array, index);
			}

			public override void CopyTo(int index, Array array, int arrayIndex, int count)
			{
				if (index < 0)
				{
					ThrowNewArgumentOutOfRangeException("index", index, "Can't be less than zero.");
				}
				if (arrayIndex < 0)
				{
					ThrowNewArgumentOutOfRangeException("arrayIndex", arrayIndex, "Can't be less than zero.");
				}
				if (count < 0)
				{
					ThrowNewArgumentOutOfRangeException("index", index, "Can't be less than zero.");
				}
				if (index >= m_Adaptee.Count)
				{
					throw new ArgumentException("Can't be more or equal to list count.", "index");
				}
				if (array.Rank > 1)
				{
					throw new ArgumentException("Can't copy into multi-dimensional array.");
				}
				if (arrayIndex >= array.Length)
				{
					throw new ArgumentException("arrayIndex can't be greater than array.Length - 1.");
				}
				if (array.Length - arrayIndex + 1 < count)
				{
					throw new ArgumentException("Destination array is too small.");
				}
				if (index > m_Adaptee.Count - count)
				{
					throw new ArgumentException("Index and count do not denote a valid range of elements.", "index");
				}
				for (int i = 0; i < count; i++)
				{
					array.SetValue(m_Adaptee[index + i], arrayIndex + i);
				}
			}

			public override IEnumerator GetEnumerator()
			{
				return m_Adaptee.GetEnumerator();
			}

			public override IEnumerator GetEnumerator(int index, int count)
			{
				CheckRange(index, count, m_Adaptee.Count);
				return new EnumeratorWithRange(m_Adaptee.GetEnumerator(), index, count);
			}

			public override void AddRange(ICollection c)
			{
				foreach (object item in c)
				{
					m_Adaptee.Add(item);
				}
			}

			public override int BinarySearch(object value)
			{
				return BinarySearch(value, null);
			}

			public override int BinarySearch(object value, IComparer comparer)
			{
				return BinarySearch(0, m_Adaptee.Count, value, comparer);
			}

			public override int BinarySearch(int index, int count, object value, IComparer comparer)
			{
				CheckRange(index, count, m_Adaptee.Count);
				if (comparer == null)
				{
					comparer = Comparer.Default;
				}
				int num = index;
				int num2 = index + count - 1;
				while (num <= num2)
				{
					int num3 = num + (num2 - num) / 2;
					int num4 = comparer.Compare(value, m_Adaptee[num3]);
					if (num4 < 0)
					{
						num2 = num3 - 1;
						continue;
					}
					if (num4 > 0)
					{
						num = num3 + 1;
						continue;
					}
					return num3;
				}
				return ~num;
			}

			public override object Clone()
			{
				return new ArrayListAdapter(m_Adaptee);
			}

			public override ArrayList GetRange(int index, int count)
			{
				CheckRange(index, count, m_Adaptee.Count);
				return new RangedArrayList(this, index, count);
			}

			public override void TrimToSize()
			{
			}

			public override void Sort()
			{
				Sort(Comparer.Default);
			}

			public override void Sort(IComparer comparer)
			{
				Sort(0, m_Adaptee.Count, comparer);
			}

			public override void Sort(int index, int count, IComparer comparer)
			{
				CheckRange(index, count, m_Adaptee.Count);
				if (comparer == null)
				{
					comparer = Comparer.Default;
				}
				QuickSort(m_Adaptee, index, index + count - 1, comparer);
			}

			private static void Swap(IList list, int x, int y)
			{
				object value = list[x];
				list[x] = list[y];
				list[y] = value;
			}

			internal static void QuickSort(IList list, int left, int right, IComparer comparer)
			{
				if (left >= right)
				{
					return;
				}
				int num = left + (right - left) / 2;
				if (comparer.Compare(list[num], list[left]) < 0)
				{
					Swap(list, num, left);
				}
				if (comparer.Compare(list[right], list[left]) < 0)
				{
					Swap(list, right, left);
				}
				if (comparer.Compare(list[right], list[num]) < 0)
				{
					Swap(list, right, num);
				}
				if (right - left + 1 <= 3)
				{
					return;
				}
				Swap(list, right - 1, num);
				object y = list[right - 1];
				int num2 = left;
				int num3 = right - 1;
				while (true)
				{
					if (comparer.Compare(list[++num2], y) >= 0)
					{
						while (comparer.Compare(list[--num3], y) > 0)
						{
						}
						if (num2 >= num3)
						{
							break;
						}
						Swap(list, num2, num3);
					}
				}
				Swap(list, right - 1, num2);
				QuickSort(list, left, num2 - 1, comparer);
				QuickSort(list, num2 + 1, right, comparer);
			}

			public override object[] ToArray()
			{
				object[] array = new object[m_Adaptee.Count];
				m_Adaptee.CopyTo(array, 0);
				return array;
			}

			public override Array ToArray(Type elementType)
			{
				Array array = Array.CreateInstance(elementType, m_Adaptee.Count);
				m_Adaptee.CopyTo(array, 0);
				return array;
			}
		}

		[Serializable]
		private class ArrayListWrapper : ArrayList
		{
			protected ArrayList m_InnerArrayList;

			public override object this[int index]
			{
				get
				{
					return m_InnerArrayList[index];
				}
				set
				{
					m_InnerArrayList[index] = value;
				}
			}

			public override int Count => m_InnerArrayList.Count;

			public override int Capacity
			{
				get
				{
					return m_InnerArrayList.Capacity;
				}
				set
				{
					m_InnerArrayList.Capacity = value;
				}
			}

			public override bool IsFixedSize => m_InnerArrayList.IsFixedSize;

			public override bool IsReadOnly => m_InnerArrayList.IsReadOnly;

			public override bool IsSynchronized => m_InnerArrayList.IsSynchronized;

			public override object SyncRoot => m_InnerArrayList.SyncRoot;

			public ArrayListWrapper(ArrayList innerArrayList)
			{
				m_InnerArrayList = innerArrayList;
			}

			public override int Add(object value)
			{
				return m_InnerArrayList.Add(value);
			}

			public override void Clear()
			{
				m_InnerArrayList.Clear();
			}

			public override bool Contains(object value)
			{
				return m_InnerArrayList.Contains(value);
			}

			public override int IndexOf(object value)
			{
				return m_InnerArrayList.IndexOf(value);
			}

			public override int IndexOf(object value, int startIndex)
			{
				return m_InnerArrayList.IndexOf(value, startIndex);
			}

			public override int IndexOf(object value, int startIndex, int count)
			{
				return m_InnerArrayList.IndexOf(value, startIndex, count);
			}

			public override int LastIndexOf(object value)
			{
				return m_InnerArrayList.LastIndexOf(value);
			}

			public override int LastIndexOf(object value, int startIndex)
			{
				return m_InnerArrayList.LastIndexOf(value, startIndex);
			}

			public override int LastIndexOf(object value, int startIndex, int count)
			{
				return m_InnerArrayList.LastIndexOf(value, startIndex, count);
			}

			public override void Insert(int index, object value)
			{
				m_InnerArrayList.Insert(index, value);
			}

			public override void InsertRange(int index, ICollection c)
			{
				m_InnerArrayList.InsertRange(index, c);
			}

			public override void Remove(object value)
			{
				m_InnerArrayList.Remove(value);
			}

			public override void RemoveAt(int index)
			{
				m_InnerArrayList.RemoveAt(index);
			}

			public override void RemoveRange(int index, int count)
			{
				m_InnerArrayList.RemoveRange(index, count);
			}

			public override void Reverse()
			{
				m_InnerArrayList.Reverse();
			}

			public override void Reverse(int index, int count)
			{
				m_InnerArrayList.Reverse(index, count);
			}

			public override void SetRange(int index, ICollection c)
			{
				m_InnerArrayList.SetRange(index, c);
			}

			public override void CopyTo(Array array)
			{
				m_InnerArrayList.CopyTo(array);
			}

			public override void CopyTo(Array array, int index)
			{
				m_InnerArrayList.CopyTo(array, index);
			}

			public override void CopyTo(int index, Array array, int arrayIndex, int count)
			{
				m_InnerArrayList.CopyTo(index, array, arrayIndex, count);
			}

			public override IEnumerator GetEnumerator()
			{
				return m_InnerArrayList.GetEnumerator();
			}

			public override IEnumerator GetEnumerator(int index, int count)
			{
				return m_InnerArrayList.GetEnumerator(index, count);
			}

			public override void AddRange(ICollection c)
			{
				m_InnerArrayList.AddRange(c);
			}

			public override int BinarySearch(object value)
			{
				return m_InnerArrayList.BinarySearch(value);
			}

			public override int BinarySearch(object value, IComparer comparer)
			{
				return m_InnerArrayList.BinarySearch(value, comparer);
			}

			public override int BinarySearch(int index, int count, object value, IComparer comparer)
			{
				return m_InnerArrayList.BinarySearch(index, count, value, comparer);
			}

			public override object Clone()
			{
				return m_InnerArrayList.Clone();
			}

			public override ArrayList GetRange(int index, int count)
			{
				return m_InnerArrayList.GetRange(index, count);
			}

			public override void TrimToSize()
			{
				m_InnerArrayList.TrimToSize();
			}

			public override void Sort()
			{
				m_InnerArrayList.Sort();
			}

			public override void Sort(IComparer comparer)
			{
				m_InnerArrayList.Sort(comparer);
			}

			public override void Sort(int index, int count, IComparer comparer)
			{
				m_InnerArrayList.Sort(index, count, comparer);
			}

			public override object[] ToArray()
			{
				return m_InnerArrayList.ToArray();
			}

			public override Array ToArray(Type elementType)
			{
				return m_InnerArrayList.ToArray(elementType);
			}
		}

		[Serializable]
		private sealed class SynchronizedArrayListWrapper : ArrayListWrapper
		{
			private object m_SyncRoot;

			public override object this[int index]
			{
				get
				{
					lock (m_SyncRoot)
					{
						return m_InnerArrayList[index];
					}
				}
				set
				{
					lock (m_SyncRoot)
					{
						m_InnerArrayList[index] = value;
					}
				}
			}

			public override int Count
			{
				get
				{
					lock (m_SyncRoot)
					{
						return m_InnerArrayList.Count;
					}
				}
			}

			public override int Capacity
			{
				get
				{
					lock (m_SyncRoot)
					{
						return m_InnerArrayList.Capacity;
					}
				}
				set
				{
					lock (m_SyncRoot)
					{
						m_InnerArrayList.Capacity = value;
					}
				}
			}

			public override bool IsFixedSize
			{
				get
				{
					lock (m_SyncRoot)
					{
						return m_InnerArrayList.IsFixedSize;
					}
				}
			}

			public override bool IsReadOnly
			{
				get
				{
					lock (m_SyncRoot)
					{
						return m_InnerArrayList.IsReadOnly;
					}
				}
			}

			public override bool IsSynchronized => true;

			public override object SyncRoot => m_SyncRoot;

			internal SynchronizedArrayListWrapper(ArrayList innerArrayList)
				: base(innerArrayList)
			{
				m_SyncRoot = innerArrayList.SyncRoot;
			}

			public override int Add(object value)
			{
				lock (m_SyncRoot)
				{
					return m_InnerArrayList.Add(value);
				}
			}

			public override void Clear()
			{
				lock (m_SyncRoot)
				{
					m_InnerArrayList.Clear();
				}
			}

			public override bool Contains(object value)
			{
				lock (m_SyncRoot)
				{
					return m_InnerArrayList.Contains(value);
				}
			}

			public override int IndexOf(object value)
			{
				lock (m_SyncRoot)
				{
					return m_InnerArrayList.IndexOf(value);
				}
			}

			public override int IndexOf(object value, int startIndex)
			{
				lock (m_SyncRoot)
				{
					return m_InnerArrayList.IndexOf(value, startIndex);
				}
			}

			public override int IndexOf(object value, int startIndex, int count)
			{
				lock (m_S