2019-08-23 11:56:54 -07:00
// This file contains portions of code released by Microsoft under the MIT license as part
// of an open-sourcing initiative in 2014 of the C# core libraries.
// The original source was submitted to https://github.com/Microsoft/referencesource
namespace System.Threading.Tasks
{
abstract class TaskScheduler
{
private static readonly TaskScheduler s_defaultTaskScheduler = new ThreadPoolTaskScheduler ( ) ~ delete _ ;
public static TaskScheduler Default
{
get
{
return s_defaultTaskScheduler ;
}
}
public static TaskScheduler Current
{
get
{
TaskScheduler current = InternalCurrent ;
return current ? ? TaskScheduler . Default ;
}
}
2020-03-09 06:34:16 -07:00
protected static TaskScheduler InternalCurrent
2019-08-23 11:56:54 -07:00
{
get
{
2020-03-09 06:34:16 -07:00
Task currentTask = Task . [ Friend ] InternalCurrent ;
2019-08-23 11:56:54 -07:00
return ( ( currentTask ! = null )
& & ( ( currentTask . CreationOptions & TaskCreationOptions . HideScheduler ) = = 0 )
2020-03-09 06:34:16 -07:00
) ? currentTask . [ Friend ] ExecutingTaskScheduler : null ;
2019-08-23 11:56:54 -07:00
}
}
2020-03-09 06:34:16 -07:00
protected abstract void QueueTask ( Task task ) ;
2019-08-23 11:56:54 -07:00
protected abstract bool TryExecuteTaskInline ( Task task , bool taskWasPreviouslyQueued ) ;
/// <summary>
/// Notifies the scheduler that a work item has made progress.
/// </summary>
2020-03-09 06:34:16 -07:00
protected virtual void NotifyWorkItemProgress ( )
2019-08-23 11:56:54 -07:00
{
}
2020-03-09 06:34:16 -07:00
protected bool TryRunInline ( Task task , bool taskWasPreviouslyQueued )
2019-08-23 11:56:54 -07:00
{
2020-03-09 06:34:16 -07:00
TaskScheduler ets = task . [ Friend ] ExecutingTaskScheduler ;
2019-08-23 11:56:54 -07:00
// Delegate cross-scheduler inlining requests to target scheduler
if ( ets ! = this & & ets ! = null ) return ets . TryRunInline ( task , taskWasPreviouslyQueued ) ;
//StackGuard currentStackGuard;
if ( ( ets = = null ) | |
2020-03-09 06:34:16 -07:00
( task . [ Friend ] m_action = = null ) | |
task . [ Friend ] IsDelegateInvoked | |
2019-08-23 11:56:54 -07:00
task . IsCanceled
//|| (currentStackGuard = Task.CurrentStackGuard).TryBeginInliningScope() == false
)
{
return false ;
}
// Task class will still call into TaskScheduler.TryRunInline rather than TryExecuteTaskInline() so that
// 1) we can adjust the return code from TryExecuteTaskInline in case a buggy custom scheduler lies to us
// 2) we maintain a mechanism for the TLS lookup optimization that we used to have for the ConcRT scheduler (will potentially introduce the same for TP)
bool bInlined = false ;
//try
{
2020-03-09 06:34:16 -07:00
task . [ Friend ] FireTaskScheduledIfNeeded ( this ) ;
2019-08-23 11:56:54 -07:00
bInlined = TryExecuteTaskInline ( task , taskWasPreviouslyQueued ) ;
}
/ * finally
{
currentStackGuard . EndInliningScope ( ) ;
} * /
// If the custom scheduler returned true, we should either have the TASK_STATE_DELEGATE_INVOKED or TASK_STATE_CANCELED bit set
// Otherwise the scheduler is buggy
/ * if ( bInlined & & ! ( task . IsDelegateInvoked | | task . IsCanceled ) )
{
throw new InvalidOperationException ( Environment . GetResourceString ( "TaskScheduler_InconsistentStateAfterTryExecuteTaskInline" ) ) ;
} * /
return bInlined ;
}
2020-03-09 06:34:16 -07:00
protected void InternalQueueTask ( Task task )
2019-08-23 11:56:54 -07:00
{
//task.FireTaskScheduledIfNeeded(this);
this . QueueTask ( task ) ;
}
2020-03-09 06:34:16 -07:00
protected virtual bool TryDequeue ( Task task )
2019-08-23 11:56:54 -07:00
{
return false ;
}
2020-03-09 06:34:16 -07:00
protected virtual bool RequiresAtomicStartTransition
2019-08-23 11:56:54 -07:00
{
get { return true ; }
}
}
}