#pragma warning disable 0420
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Security;
using System.Security.Permissions;
using System.Collections.Concurrent;
using System.Diagnostics.Contracts;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace System.Threading.Tasks
{
[DebuggerDisplay("Id={Id}")]
[DebuggerTypeProxy(typeof(SystemThreadingTasks_TaskSchedulerDebugView))]
[HostProtection(Synchronization = true, ExternalThreading = true)]
#pragma warning disable 618
[PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)]
#pragma warning restore 618
public abstract class TaskScheduler
{
[SecurityCritical]
protected internal abstract void QueueTask(Task task);
[SecurityCritical]
protected abstract bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued);
[SecurityCritical]
protected abstract IEnumerable<Task> GetScheduledTasks();
public virtual Int32 MaximumConcurrencyLevel
{
get
{
return Int32.MaxValue;
}
}
[SecuritySafeCritical]
internal bool TryRunInline(Task task, bool taskWasPreviouslyQueued)
{
TaskScheduler ets = task.ExecutingTaskScheduler;
if(ets != this && ets !=null) return ets.TryRunInline(task, taskWasPreviouslyQueued);
StackGuard currentStackGuard;
if( (ets == null) ||
(task.m_action == null) ||
task.IsDelegateInvoked ||
task.IsCanceled ||
(currentStackGuard = Task.CurrentStackGuard).TryBeginInliningScope() == false)
{
return false;
}
bool bInlined = false;
try
{
task.FireTaskScheduledIfNeeded(this);
bInlined = TryExecuteTaskInline(task, taskWasPreviouslyQueued);
}
finally
{
currentStackGuard.EndInliningScope();
}
if (bInlined && !(task.IsDelegateInvoked || task.IsCanceled))
{
throw new InvalidOperationException(Environment.GetResourceString("TaskScheduler_InconsistentStateAfterTryExecuteTaskInline"));
}
return bInlined;
}
[SecurityCritical]
protected internal virtual bool TryDequeue(Task task)
{
return false;
}
internal virtual void NotifyWorkItemProgress()
{
}
internal virtual bool RequiresAtomicStartTransition
{
get { return true; }
}
[SecurityCritical]
internal void InternalQueueTask(Task task)
{
Contract.Requires(task != null);
task.FireTaskScheduledIfNeeded(this);
this.QueueTask(task);
}
private static readonly ConditionalWeakTable<TaskScheduler, object> s_activeTaskSchedulers = new ConditionalWeakTable<TaskScheduler,object>();
private static readonly TaskScheduler s_defaultTaskScheduler = new ThreadPoolTaskScheduler();
internal static int s_taskSchedulerIdCounter;
private volatile int m_taskSchedulerId;
protected TaskScheduler()
{
Contract.Assert(s_activeTaskSchedulers != null, "Expected non-null s_activeTaskSchedulers");
s_activeTaskSchedulers.Add(this, null);
}
public static TaskScheduler Default
{
get
{
return s_defaultTaskScheduler;
}
}
public static TaskScheduler Current
{
get
{
TaskScheduler current = InternalCurrent;
return current ?? TaskScheduler.Default;
}
}
internal static TaskScheduler InternalCurrent
{
get
{
Task currentTask = Task.InternalCurrent;
return ( (currentTask != null)
&& ((currentTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)
) ? currentTask.ExecutingTaskScheduler : null;
}
}
public static TaskScheduler FromCurrentSynchronizationContext()
{
return new SynchronizationContextTaskScheduler();
}
public Int32 Id
{
get
{
if (m_taskSchedulerId == 0)
{
int newId = 0;
do
{
newId = Interlocked.Increment(ref s_taskSchedulerIdCounter);
} while (newId == 0);
Interlocked.CompareExchange(ref m_taskSchedulerId, newId, 0);
}
return m_taskSchedulerId;
}
}
[SecurityCritical]
protected bool TryExecuteTask(Task task)
{
if (task.ExecutingTaskScheduler != this)
{
throw new InvalidOperationException(Environment.GetResourceString("TaskScheduler_ExecuteTask_WrongTaskScheduler"));
}
return task.ExecuteEntry(true);
}
private static EventHandler<UnobservedTaskExceptionEventArgs> _unobservedTaskException;
private static readonly object _unobservedTaskExceptionLockObject = new object();
public static event EventHandler<UnobservedTaskExceptionEventArgs> UnobservedTaskException
{
[System.Security.SecurityCritical]
add
{
if (value != null)
{
#if !PFX_LEGACY_3_5
RuntimeHelpers.PrepareContractedDelegate(value);
#endif
lock (_unobservedTaskExceptionLockObject) _unobservedTaskException += value;
}
}
[System.Security.SecurityCritical]
remove
{
lock (_unobservedTaskExceptionLockObject) _unobservedTaskException -= value;
}
}
internal static void PublishUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs ueea)
{
lock (_unobservedTaskExceptionLockObject)
{
EventHandler<UnobservedTaskExceptionEventArgs> handler = _unobservedTaskException;
if (handler != null)
{
handler(sender, ueea);
}
}
}
[SecurityCritical]
internal Task[] GetScheduledTasksForDebugger()
{
IEnumerable<Task> activeTasksSource = GetScheduledTasks();
if (activeTasksSource == null)
return null;
Task[] activeTasksArray = activeTasksSource as Task[];
if (activeTasksArray == null)
{
activeTasksArray = (new List<Task>(activeTasksSource)).ToArray();
}
foreach (Task t in activeTasksArray)
{
int tmp = t.Id;
}
return activeTasksArray;
}
[SecurityCritical]
internal static TaskScheduler[] GetTaskSchedulersForDebugger()
{
Contract.Assert(s_activeTaskSchedulers != null, "Expected non-null s_activeTaskSchedulers");
ICollection<TaskScheduler> schedulers = s_activeTaskSchedulers.Keys;
var arr = new TaskScheduler[schedulers.Count];
schedulers.CopyTo(arr, 0);
foreach (var scheduler in arr)
{
Contract.Assert(scheduler != null, "Table returned an incorrect Count or CopyTo failed");
int tmp = scheduler.Id;
}
return arr;
}
internal sealed class SystemThreadingTasks_TaskSchedulerDebugView
{
private readonly TaskScheduler m_taskScheduler;
public SystemThreadingTasks_TaskSchedulerDebugView(TaskScheduler scheduler)
{
m_taskScheduler = scheduler;
}
public Int32 Id
{
get { return m_taskScheduler.Id; }
}
public IEnumerable<Task> ScheduledTasks
{
[SecurityCritical]
get { return m_taskScheduler.GetScheduledTasks(); }
}
}
}
internal sealed class SynchronizationContextTaskScheduler : TaskScheduler
{
private SynchronizationContext m_synchronizationContext;
internal SynchronizationContextTaskScheduler()
{
SynchronizationContext synContext = SynchronizationContext.Current;
if (synContext == null)
{
throw new InvalidOperationException(Environment.GetResourceString("TaskScheduler_FromCurrentSynchronizationContext_NoCurrent"));
}
m_synchronizationContext = synContext;
}
[SecurityCritical]
protected internal override void QueueTask(Task task)
{
m_synchronizationContext.Post(s_postCallback, (object)task);
}
[SecurityCritical]
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
if (SynchronizationContext.Current == m_synchronizationContext)
{
return TryExecuteTask(task);
}
else
return false;
}
[SecurityCritical]
protected override IEnumerable<Task> GetScheduledTasks()
{
return null;
}
public override Int32 MaximumConcurrencyLevel
{
get
{
return 1;
}
}
private static SendOrPostCallback s_postCallback = new SendOrPostCallback(PostCallback);
private static void PostCallback(object obj)
{
Task task = (Task) obj;
task.ExecuteEntry(true);
}
}
public class UnobservedTaskExceptionEventArgs : EventArgs
{
private AggregateException m_exception;
internal bool m_observed = false;
public UnobservedTaskExceptionEventArgs(AggregateException exception) { m_exception = exception; }
public void SetObserved() { m_observed = true; }
public bool Observed { get { return m_observed; } }
public AggregateException Exception { get { return m_exception; } }
}
}