summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Threading/Tasks/Task.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Threading/Tasks/Task.cs')
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/Task.cs229
1 files changed, 78 insertions, 151 deletions
diff --git a/src/mscorlib/src/System/Threading/Tasks/Task.cs b/src/mscorlib/src/System/Threading/Tasks/Task.cs
index 36f8401a4d..cf081f75fd 100644
--- a/src/mscorlib/src/System/Threading/Tasks/Task.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/Task.cs
@@ -137,7 +137,6 @@ namespace System.Threading.Tasks
/// InternalWait method serves a potential marker for when a Task is entering a wait operation.
/// </para>
/// </remarks>
- [HostProtection(Synchronization = true, ExternalThreading = true)]
[DebuggerTypeProxy(typeof(SystemThreadingTasks_TaskDebugView))]
[DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}")]
public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable
@@ -152,7 +151,7 @@ namespace System.Threading.Tasks
private volatile int m_taskId; // this task's unique ID. initialized only if it is ever requested
- internal object m_action; // The body of the task. Might be Action<object>, Action<TState> or Action. Or possibly a Func.
+ internal Delegate m_action; // The body of the task. Might be Action<object>, Action<TState> or Action. Or possibly a Func.
// If m_action is set to null it will indicate that we operate in the
// "externally triggered completion" mode, which is exclusively meant
// for the signalling Task<TResult> (aka. promise). In this mode,
@@ -339,7 +338,7 @@ namespace System.Threading.Tasks
// (action,TCO). It should always be true.
internal Task(object state, TaskCreationOptions creationOptions, bool promiseStyle)
{
- Contract.Assert(promiseStyle, "Promise CTOR: promiseStyle was false");
+ Debug.Assert(promiseStyle, "Promise CTOR: promiseStyle was false");
// Check the creationOptions. We allow the AttachedToParent option to be specified for promise tasks.
// Also allow RunContinuationsAsynchronously because this is the constructor called by TCS
@@ -580,7 +579,7 @@ namespace System.Threading.Tasks
/// <param name="cancellationToken">A CancellationToken for the Task.</param>
/// <param name="creationOptions">Options to customize behavior of Task.</param>
/// <param name="internalOptions">Internal options to customize behavior of Task.</param>
- internal void TaskConstructorCore(object action, object state, CancellationToken cancellationToken,
+ internal void TaskConstructorCore(Delegate action, object state, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
{
m_action = action;
@@ -609,7 +608,7 @@ namespace System.Threading.Tasks
InternalTaskOptions.ContinuationTask |
InternalTaskOptions.LazyCancellation |
InternalTaskOptions.QueuedByRuntime));
- Contract.Assert(illegalInternalOptions == 0, "TaskConstructorCore: Illegal internal options");
+ Debug.Assert(illegalInternalOptions == 0, "TaskConstructorCore: Illegal internal options");
#endif
// Throw exception if the user specifies both LongRunning and SelfReplicating
@@ -620,8 +619,8 @@ namespace System.Threading.Tasks
}
// Assign options to m_stateAndOptionsFlag.
- Contract.Assert(m_stateFlags == 0, "TaskConstructorCore: non-zero m_stateFlags");
- Contract.Assert((((int)creationOptions) | OptionsMask) == OptionsMask, "TaskConstructorCore: options take too many bits");
+ Debug.Assert(m_stateFlags == 0, "TaskConstructorCore: non-zero m_stateFlags");
+ Debug.Assert((((int)creationOptions) | OptionsMask) == OptionsMask, "TaskConstructorCore: options take too many bits");
var tmpFlags = (int)creationOptions | (int)internalOptions;
if ((m_action == null) || ((internalOptions & InternalTaskOptions.ContinuationTask) != 0))
{
@@ -649,7 +648,7 @@ namespace System.Threading.Tasks
// we need to do this as the very last thing in the construction path, because the CT registration could modify m_stateFlags
if (cancellationToken.CanBeCanceled)
{
- Contract.Assert((internalOptions &
+ Debug.Assert((internalOptions &
(InternalTaskOptions.ChildReplica | InternalTaskOptions.SelfReplicating | InternalTaskOptions.ContinuationTask)) == 0,
"TaskConstructorCore: Did not expect to see cancelable token for replica/replicating or continuation task.");
@@ -743,7 +742,7 @@ namespace System.Threading.Tasks
antecedentTask.RemoveContinuation(continuation);
}
}
- Contract.Assert(targetTask != null,
+ Debug.Assert(targetTask != null,
"targetTask should have been non-null, with the supplied argument being a task or a tuple containing one");
targetTask.InternalCancel(false);
}
@@ -753,7 +752,7 @@ namespace System.Threading.Tasks
{
get
{
- Delegate d = (Delegate)m_action;
+ Delegate d = m_action;
return d != null ? d.Method.ToString() : "{null}";
}
}
@@ -764,10 +763,9 @@ namespace System.Threading.Tasks
/// </summary>
/// <param name="stackMark">A stack crawl mark pointing to the frame of the caller.</param>
- [SecuritySafeCritical]
internal void PossiblyCaptureContext(ref StackCrawlMark stackMark)
{
- Contract.Assert(m_contingentProperties == null || m_contingentProperties.m_capturedContext == null,
+ Debug.Assert(m_contingentProperties == null || m_contingentProperties.m_capturedContext == null,
"Captured an ExecutionContext when one was already captured.");
// In the legacy .NET 3.5 build, we don't have the optimized overload of Capture()
@@ -791,7 +789,7 @@ namespace System.Threading.Tasks
// a read of the volatile m_stateFlags field.
internal static TaskCreationOptions OptionsMethod(int flags)
{
- Contract.Assert((OptionsMask & 1) == 1, "OptionsMask needs a shift in Options.get");
+ Debug.Assert((OptionsMask & 1) == 1, "OptionsMask needs a shift in Options.get");
return (TaskCreationOptions)(flags & OptionsMask);
}
@@ -841,7 +839,7 @@ namespace System.Threading.Tasks
/// <param name="enabled">true to set the bit; false to unset the bit.</param>
internal void SetNotificationForWaitCompletion(bool enabled)
{
- Contract.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0,
+ Debug.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0,
"Should only be used for promise-style tasks"); // hasn't been vetted on other kinds as there hasn't been a need
if (enabled)
@@ -849,7 +847,7 @@ namespace System.Threading.Tasks
// Atomically set the END_AWAIT_NOTIFICATION bit
bool success = AtomicStateUpdate(TASK_STATE_WAIT_COMPLETION_NOTIFICATION,
TASK_STATE_COMPLETED_MASK | TASK_STATE_COMPLETION_RESERVED);
- Contract.Assert(success, "Tried to set enabled on completed Task");
+ Debug.Assert(success, "Tried to set enabled on completed Task");
}
else
{
@@ -886,7 +884,7 @@ namespace System.Threading.Tasks
/// <returns>true if any of the tasks require notification; otherwise, false.</returns>
internal static bool AnyTaskRequiresNotifyDebuggerOfWaitCompletion(Task[] tasks)
{
- Contract.Assert(tasks != null, "Expected non-null array of tasks");
+ Debug.Assert(tasks != null, "Expected non-null array of tasks");
foreach (var task in tasks)
{
if (task != null &&
@@ -926,7 +924,7 @@ namespace System.Threading.Tasks
// bit was unset between the time that it was checked and this method was called.
// It's so remote a chance that it's worth having the assert to protect against misuse.
bool isWaitNotificationEnabled = IsWaitNotificationEnabled;
- Contract.Assert(isWaitNotificationEnabled, "Should only be called if the wait completion bit is set.");
+ Debug.Assert(isWaitNotificationEnabled, "Should only be called if the wait completion bit is set.");
return isWaitNotificationEnabled;
}
}
@@ -946,7 +944,7 @@ namespace System.Threading.Tasks
// It's theoretically possible but extremely rare that this assert could fire because the
// bit was unset between the time that it was checked and this method was called.
// It's so remote a chance that it's worth having the assert to protect against misuse.
- Contract.Assert(IsWaitNotificationEnabled, "Should only be called if the wait completion bit is set.");
+ Debug.Assert(IsWaitNotificationEnabled, "Should only be called if the wait completion bit is set.");
// Now that we're notifying the debugger, clear the bit. The debugger should do this anyway,
// but this adds a bit of protection in case it fails to, and given that the debugger is involved,
@@ -991,7 +989,7 @@ namespace System.Threading.Tasks
/// </summary>
internal void AddNewChild()
{
- Contract.Assert(Task.InternalCurrent == this || this.IsSelfReplicatingRoot, "Task.AddNewChild(): Called from an external context");
+ Debug.Assert(Task.InternalCurrent == this || this.IsSelfReplicatingRoot, "Task.AddNewChild(): Called from an external context");
var props = EnsureContingentPropertiesInitialized();
@@ -1014,10 +1012,10 @@ namespace System.Threading.Tasks
// We need to subtract that child from m_completionCountdown, or the parent will never complete.
internal void DisregardChild()
{
- Contract.Assert(Task.InternalCurrent == this, "Task.DisregardChild(): Called from an external context");
+ Debug.Assert(Task.InternalCurrent == this, "Task.DisregardChild(): Called from an external context");
var props = EnsureContingentPropertiesInitialized();
- Contract.Assert(props.m_completionCountdown >= 2, "Task.DisregardChild(): Expected parent count to be >= 2");
+ Debug.Assert(props.m_completionCountdown >= 2, "Task.DisregardChild(): Expected parent count to be >= 2");
Interlocked.Decrement(ref props.m_completionCountdown);
}
@@ -1161,7 +1159,6 @@ namespace System.Threading.Tasks
//
// Internal version of RunSynchronously that allows not waiting for completion.
//
- [SecuritySafeCritical] // Needed for QueueTask
internal void InternalRunSynchronously(TaskScheduler scheduler, bool waitForCompletion)
{
Contract.Requires(scheduler != null, "Task.InternalRunSynchronously(): null TaskScheduler");
@@ -1235,7 +1232,7 @@ namespace System.Threading.Tasks
// Mark ourselves as "handled" to avoid crashing the finalizer thread if the caller neglects to
// call Wait() on this task.
// m_contingentProperties.m_exceptionsHolder *should* already exist after AddException()
- Contract.Assert(
+ Debug.Assert(
(m_contingentProperties != null) &&
(m_contingentProperties.m_exceptionsHolder != null) &&
(m_contingentProperties.m_exceptionsHolder.ContainsFaultList),
@@ -1252,7 +1249,7 @@ namespace System.Threading.Tasks
}
else
{
- Contract.Assert((m_stateFlags & TASK_STATE_CANCELED) != 0, "Task.RunSynchronously: expected TASK_STATE_CANCELED to be set");
+ Debug.Assert((m_stateFlags & TASK_STATE_CANCELED) != 0, "Task.RunSynchronously: expected TASK_STATE_CANCELED to be set");
// Can't call this method on canceled task.
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_RunSynchronously_TaskCompleted);
}
@@ -1403,7 +1400,7 @@ namespace System.Threading.Tasks
// Only return an exception in faulted state (skip manufactured exceptions)
// A "benevolent" race condition makes it possible to return null when IsFaulted is
// true (i.e., if IsFaulted is set just after the check to IsFaulted above).
- Contract.Assert((e == null) || IsFaulted, "Task.Exception_get(): returning non-null value when not Faulted");
+ Debug.Assert((e == null) || IsFaulted, "Task.Exception_get(): returning non-null value when not Faulted");
return e;
}
@@ -1884,11 +1881,10 @@ namespace System.Threading.Tasks
/// underneath us. If false, TASK_STATE_STARTED bit is OR-ed right in. This
/// allows us to streamline things a bit for StartNew(), where competing cancellations
/// are not a problem.</param>
- [SecuritySafeCritical] // Needed for QueueTask
internal void ScheduleAndStart(bool needsProtection)
{
- Contract.Assert(m_taskScheduler != null, "expected a task scheduler to have been selected");
- Contract.Assert((m_stateFlags & TASK_STATE_STARTED) == 0, "task has already started");
+ Debug.Assert(m_taskScheduler != null, "expected a task scheduler to have been selected");
+ Debug.Assert((m_stateFlags & TASK_STATE_STARTED) == 0, "task has already started");
// Set the TASK_STATE_STARTED bit
if (needsProtection)
@@ -1912,7 +1908,7 @@ namespace System.Threading.Tasks
if (AsyncCausalityTracer.LoggingOn && (Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) == 0)
{
//For all other task than TaskContinuations we want to log. TaskContinuations log in their constructor
- AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task: "+((Delegate)m_action).Method.Name, 0);
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task: " + m_action.Method.Name, 0);
}
@@ -1942,7 +1938,7 @@ namespace System.Threading.Tasks
if ((Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) == 0)
{
// m_contingentProperties.m_exceptionsHolder *should* already exist after AddException()
- Contract.Assert(
+ Debug.Assert(
(m_contingentProperties != null) &&
(m_contingentProperties.m_exceptionsHolder != null) &&
(m_contingentProperties.m_exceptionsHolder.ContainsFaultList),
@@ -1981,13 +1977,13 @@ namespace System.Threading.Tasks
var eoAsEdi = exceptionObject as ExceptionDispatchInfo;
var eoAsEnumerableEdi = exceptionObject as IEnumerable<ExceptionDispatchInfo>;
- Contract.Assert(
+ Debug.Assert(
eoAsException != null || eoAsEnumerableException != null || eoAsEdi != null || eoAsEnumerableEdi != null,
"Task.AddException: Expected an Exception, ExceptionDispatchInfo, or an IEnumerable<> of one of those");
var eoAsOce = exceptionObject as OperationCanceledException;
- Contract.Assert(
+ Debug.Assert(
!representsCancellation ||
eoAsOce != null ||
(eoAsEdi != null && eoAsEdi.SourceException is OperationCanceledException),
@@ -2078,7 +2074,7 @@ namespace System.Threading.Tasks
{
// There are exceptions; get the aggregate and optionally add the canceled
// exception to the aggregate (if applicable).
- Contract.Assert(m_contingentProperties != null); // ExceptionRecorded ==> m_contingentProperties != null
+ Debug.Assert(m_contingentProperties != null); // ExceptionRecorded ==> m_contingentProperties != null
// No need to lock around this, as other logic prevents the consumption of exceptions
// before they have been completely processed.
@@ -2097,7 +2093,7 @@ namespace System.Threading.Tasks
internal ReadOnlyCollection<ExceptionDispatchInfo> GetExceptionDispatchInfos()
{
bool exceptionsAvailable = IsFaulted && ExceptionRecorded;
- Contract.Assert(exceptionsAvailable, "Must only be used when the task has faulted with exceptions.");
+ Debug.Assert(exceptionsAvailable, "Must only be used when the task has faulted with exceptions.");
return exceptionsAvailable ?
m_contingentProperties.m_exceptionsHolder.GetExceptionDispatchInfos() :
new ReadOnlyCollection<ExceptionDispatchInfo>(new ExceptionDispatchInfo[0]);
@@ -2107,7 +2103,7 @@ namespace System.Threading.Tasks
/// <returns>The ExceptionDispatchInfo. May be null if no OCE was stored for the task.</returns>
internal ExceptionDispatchInfo GetCancellationExceptionDispatchInfo()
{
- Contract.Assert(IsCanceled, "Must only be used when the task has canceled.");
+ Debug.Assert(IsCanceled, "Must only be used when the task has canceled.");
return Volatile.Read(ref m_contingentProperties)?.m_exceptionsHolder?.GetCancellationExceptionDispatchInfo(); // may be null
}
@@ -2344,7 +2340,7 @@ namespace System.Threading.Tasks
Contract.Requires(childTask != null);
Contract.Requires(childTask.IsCompleted, "ProcessChildCompletion was called for an uncompleted task");
- Contract.Assert(childTask.m_contingentProperties?.m_parent == this, "ProcessChildCompletion should only be called for a child of this task");
+ Debug.Assert(childTask.m_contingentProperties?.m_parent == this, "ProcessChildCompletion should only be called for a child of this task");
var props = Volatile.Read(ref m_contingentProperties);
@@ -2404,11 +2400,11 @@ namespace System.Threading.Tasks
{
// Ensure any exceptions thrown by children are added to the parent.
// In doing this, we are implicitly marking children as being "handled".
- Contract.Assert(task.IsCompleted, "Expected all tasks in list to be completed");
+ Debug.Assert(task.IsCompleted, "Expected all tasks in list to be completed");
if (task.IsFaulted && !task.IsExceptionObservedByParent)
{
TaskExceptionHolder exceptionHolder = Volatile.Read(ref task.m_contingentProperties).m_exceptionsHolder;
- Contract.Assert(exceptionHolder != null);
+ Debug.Assert(exceptionHolder != null);
// No locking necessary since child task is finished adding exceptions
// and concurrent CreateExceptionObject() calls do not constitute
@@ -2435,7 +2431,7 @@ namespace System.Threading.Tasks
/// <param name="delegateRan">Whether the delegate was executed.</param>
internal void FinishThreadAbortedTask(bool bTAEAddedToExceptionHolder, bool delegateRan)
{
- Contract.Assert(!bTAEAddedToExceptionHolder || m_contingentProperties?.m_exceptionsHolder != null,
+ Debug.Assert(!bTAEAddedToExceptionHolder || m_contingentProperties?.m_exceptionsHolder != null,
"FinishThreadAbortedTask() called on a task whose exception holder wasn't initialized");
// this will only be false for non-root self replicating task copies, because all of their exceptions go to the root task.
@@ -2671,7 +2667,6 @@ namespace System.Threading.Tasks
/// IThreadPoolWorkItem override, which is the entry function for this task when the TP scheduler decides to run it.
///
/// </summary>
- [SecurityCritical]
void IThreadPoolWorkItem.ExecuteWorkItem()
{
ExecuteEntry(false);
@@ -2681,7 +2676,6 @@ namespace System.Threading.Tasks
/// The ThreadPool calls this if a ThreadAbortException is thrown while trying to execute this workitem. This may occur
/// before Task would otherwise be able to observe it.
/// </summary>
- [SecurityCritical]
void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae)
{
// If the task has marked itself as Completed, then it either a) already observed this exception (so we shouldn't handle it here)
@@ -2700,7 +2694,6 @@ namespace System.Threading.Tasks
/// </summary>
/// <param name="bPreventDoubleExecution"> Performs atomic updates to prevent double execution. Should only be set to true
/// in codepaths servicing user provided TaskSchedulers. The ConcRT or ThreadPool schedulers don't need this. </param>
- [SecuritySafeCritical]
internal bool ExecuteEntry(bool bPreventDoubleExecution)
{
if (bPreventDoubleExecution || ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0))
@@ -2742,7 +2735,6 @@ namespace System.Threading.Tasks
}
// A trick so we can refer to the TLS slot with a byref.
- [SecurityCritical]
private void ExecuteWithThreadLocal(ref Task currentTaskSlot)
{
// Remember the current task so we can restore it after running, and then
@@ -2819,14 +2811,12 @@ namespace System.Threading.Tasks
}
// Cached callback delegate that's lazily initialized due to ContextCallback being SecurityCritical
- [SecurityCritical]
private static ContextCallback s_ecCallback;
- [SecurityCritical]
private static void ExecutionContextCallback(object obj)
{
Task task = obj as Task;
- Contract.Assert(task != null, "expected a task object");
+ Debug.Assert(task != null, "expected a task object");
task.Execute();
}
@@ -2837,7 +2827,7 @@ namespace System.Threading.Tasks
internal virtual void InnerInvoke()
{
// Invoke the delegate
- Contract.Assert(m_action != null, "Null action in InnerInvoke()");
+ Debug.Assert(m_action != null, "Null action in InnerInvoke()");
var action = m_action as Action;
if (action != null)
{
@@ -2850,7 +2840,7 @@ namespace System.Threading.Tasks
actionWithState(m_stateObject);
return;
}
- Contract.Assert(false, "Invalid m_action in Task");
+ Debug.Assert(false, "Invalid m_action in Task");
}
/// <summary>
@@ -2929,7 +2919,6 @@ namespace System.Threading.Tasks
/// <param name="flowExecutionContext">Whether to flow ExecutionContext across the await.</param>
/// <param name="stackMark">A stack crawl mark tied to execution context.</param>
/// <exception cref="System.InvalidOperationException">The awaiter was not properly initialized.</exception>
- [SecurityCritical]
internal void SetContinuationForAwait(
Action continuationAction, bool continueOnCapturedContext, bool flowExecutionContext, ref StackCrawlMark stackMark)
{
@@ -2986,7 +2975,7 @@ namespace System.Threading.Tasks
}
else
{
- Contract.Assert(!flowExecutionContext, "We already determined we're not required to flow context.");
+ Debug.Assert(!flowExecutionContext, "We already determined we're not required to flow context.");
if (!AddTaskContinuation(continuationAction, addBeforeOthers: false))
AwaitTaskContinuation.UnsafeScheduleAction(continuationAction, this);
}
@@ -3019,7 +3008,7 @@ namespace System.Threading.Tasks
Wait(Timeout.Infinite, default(CancellationToken));
#if DEBUG
- Contract.Assert(waitResult, "expected wait to succeed");
+ Debug.Assert(waitResult, "expected wait to succeed");
#endif
}
@@ -3154,7 +3143,7 @@ namespace System.Threading.Tasks
ThrowIfExceptional(true);
}
- Contract.Assert((m_stateFlags & TASK_STATE_FAULTED) == 0, "Task.Wait() completing when in Faulted state.");
+ Debug.Assert((m_stateFlags & TASK_STATE_FAULTED) == 0, "Task.Wait() completing when in Faulted state.");
return true;
}
@@ -3230,7 +3219,7 @@ namespace System.Threading.Tasks
}
}
- Contract.Assert(IsCompleted || millisecondsTimeout != Timeout.Infinite);
+ Debug.Assert(IsCompleted || millisecondsTimeout != Timeout.Infinite);
// ETW event for Task Wait End
if (etwIsEnabled)
@@ -3358,7 +3347,6 @@ namespace System.Threading.Tasks
/// For custom schedulers we also attempt an atomic state transition.
/// </param>
/// <returns>true if the task was successfully canceled; otherwise, false.</returns>
- [SecuritySafeCritical]
internal bool InternalCancel(bool bCancelNonExecutingOnly)
{
Contract.Requires((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) == 0, "Task.InternalCancel() did not expect promise-style task");
@@ -3426,7 +3414,7 @@ namespace System.Threading.Tasks
if (bPopSucceeded)
{
// hitting this would mean something wrong with the AtomicStateUpdate above
- Contract.Assert(!mustCleanup, "Possibly an invalid state transition call was made in InternalCancel()");
+ Debug.Assert(!mustCleanup, "Possibly an invalid state transition call was made in InternalCancel()");
// Include TASK_STATE_DELEGATE_INVOKED in "illegal" bits to protect against the situation where
// TS.TryDequeue() returns true but the task is still left on the queue.
@@ -3466,8 +3454,8 @@ namespace System.Threading.Tasks
{
RecordInternalCancellationRequest();
- Contract.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0, "Task.RecordInternalCancellationRequest(CancellationToken) only valid for promise-style task");
- Contract.Assert(m_contingentProperties.m_cancellationToken == default(CancellationToken));
+ Debug.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0, "Task.RecordInternalCancellationRequest(CancellationToken) only valid for promise-style task");
+ Debug.Assert(m_contingentProperties.m_cancellationToken == default(CancellationToken));
// Store the supplied cancellation token as this task's token.
// Waiting on this task will then result in an OperationCanceledException containing this token.
@@ -3492,11 +3480,11 @@ namespace System.Threading.Tasks
if (oce == null)
{
var edi = cancellationException as ExceptionDispatchInfo;
- Contract.Assert(edi != null, "Expected either an OCE or an EDI");
+ Debug.Assert(edi != null, "Expected either an OCE or an EDI");
oce = edi.SourceException as OperationCanceledException;
- Contract.Assert(oce != null, "Expected EDI to contain an OCE");
+ Debug.Assert(oce != null, "Expected EDI to contain an OCE");
}
- Contract.Assert(oce.CancellationToken == tokenToRecord,
+ Debug.Assert(oce.CancellationToken == tokenToRecord,
"Expected OCE's token to match the provided token.");
#endif
AddException(cancellationException, representsCancellation: true);
@@ -3507,10 +3495,10 @@ namespace System.Threading.Tasks
// And this method should be called at most once per task.
internal void CancellationCleanupLogic()
{
- Contract.Assert((m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_COMPLETION_RESERVED)) != 0, "Task.CancellationCleanupLogic(): Task not canceled or reserved.");
+ Debug.Assert((m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_COMPLETION_RESERVED)) != 0, "Task.CancellationCleanupLogic(): Task not canceled or reserved.");
// I'd like to do this, but there is a small window for a race condition. If someone calls Wait() between InternalCancel() and
// here, that will set m_completionEvent, leading to a meaningless/harmless assertion.
- //Contract.Assert((m_completionEvent == null) || !m_completionEvent.IsSet, "Task.CancellationCleanupLogic(): Completion event already set.");
+ //Debug.Assert((m_completionEvent == null) || !m_completionEvent.IsSet, "Task.CancellationCleanupLogic(): Completion event already set.");
// This may have been set already, but we need to make sure.
Interlocked.Exchange(ref m_stateFlags, m_stateFlags | TASK_STATE_CANCELED);
@@ -3541,8 +3529,8 @@ namespace System.Threading.Tasks
/// </summary>
private void SetCancellationAcknowledged()
{
- Contract.Assert(this == Task.InternalCurrent, "SetCancellationAcknowledged() should only be called while this is still the current task");
- Contract.Assert(IsCancellationRequested, "SetCancellationAcknowledged() should not be called if the task's CT wasn't signaled");
+ Debug.Assert(this == Task.InternalCurrent, "SetCancellationAcknowledged() should only be called while this is still the current task");
+ Debug.Assert(IsCancellationRequested, "SetCancellationAcknowledged() should not be called if the task's CT wasn't signaled");
m_stateFlags |= TASK_STATE_CANCELLATIONACKNOWLEDGED;
}
@@ -3558,7 +3546,6 @@ namespace System.Threading.Tasks
/// <summary>
/// Runs all of the continuations, as appropriate.
/// </summary>
- [SecuritySafeCritical] // for AwaitTaskContinuation.RunOrScheduleAction
internal void FinishContinuations()
{
// Atomically store the fact that this task is completing. From this point on, the adding of continuations will
@@ -3684,7 +3671,7 @@ namespace System.Threading.Tasks
// Otherwise, it must be an ITaskCompletionAction, so invoke it.
else
{
- Contract.Assert(currentContinuation is ITaskCompletionAction, "Expected continuation element to be Action, TaskContinuation, or ITaskContinuationAction");
+ Debug.Assert(currentContinuation is ITaskCompletionAction, "Expected continuation element to be Action, TaskContinuation, or ITaskContinuationAction");
var action = (ITaskCompletionAction)currentContinuation;
if (bCanInlineContinuations || !action.InvokeMayRunArbitraryCode)
@@ -4730,7 +4717,7 @@ namespace System.Threading.Tasks
// m_continuationObject is guaranteed at this point to be either a List or
// s_taskCompletionSentinel.
List<object> list = m_continuationObject as List<object>;
- Contract.Assert((list != null) || (m_continuationObject == s_taskCompletionSentinel),
+ Debug.Assert((list != null) || (m_continuationObject == s_taskCompletionSentinel),
"Expected m_continuationObject to be list or sentinel");
// If list is null, it can only mean that s_taskCompletionSentinel has been exchanged
@@ -4873,7 +4860,7 @@ namespace System.Threading.Tasks
WaitAll(tasks, Timeout.Infinite);
#if DEBUG
- Contract.Assert(waitResult, "expected wait to succeed");
+ Debug.Assert(waitResult, "expected wait to succeed");
#endif
}
@@ -5134,7 +5121,7 @@ namespace System.Threading.Tasks
// Now gather up and throw all of the exceptions.
foreach (var task in tasks) AddExceptionsForCompletedTask(ref exceptions, task);
- Contract.Assert(exceptions != null, "Should have seen at least one exception");
+ Debug.Assert(exceptions != null, "Should have seen at least one exception");
ThrowHelper.ThrowAggregateException(exceptions);
}
@@ -5159,8 +5146,8 @@ namespace System.Threading.Tasks
/// <returns>true if all of the tasks completed; otherwise, false.</returns>
private static bool WaitAllBlockingCore(List<Task> tasks, int millisecondsTimeout, CancellationToken cancellationToken)
{
- Contract.Assert(tasks != null, "Expected a non-null list of tasks");
- Contract.Assert(tasks.Count > 0, "Expected at least one task");
+ Debug.Assert(tasks != null, "Expected a non-null list of tasks");
+ Debug.Assert(tasks.Count > 0, "Expected at least one task");
bool waitCompleted = false;
var mres = new SetOnCountdownMres(tasks.Count);
@@ -5206,14 +5193,14 @@ namespace System.Threading.Tasks
internal SetOnCountdownMres(int count)
{
- Contract.Assert(count > 0, "Expected count > 0");
+ Debug.Assert(count > 0, "Expected count > 0");
_count = count;
}
public void Invoke(Task completingTask)
{
if (Interlocked.Decrement(ref _count) == 0) Set();
- Contract.Assert(_count >= 0, "Count should never go below 0");
+ Debug.Assert(_count >= 0, "Count should never go below 0");
}
public bool InvokeMayRunArbitraryCode { get { return false; } }
@@ -5304,7 +5291,7 @@ namespace System.Threading.Tasks
public static int WaitAny(params Task[] tasks)
{
int waitResult = WaitAny(tasks, Timeout.Infinite);
- Contract.Assert(tasks.Length == 0 || waitResult != -1, "expected wait to succeed");
+ Debug.Assert(tasks.Length == 0 || waitResult != -1, "expected wait to succeed");
return waitResult;
}
@@ -5475,9 +5462,9 @@ namespace System.Threading.Tasks
bool waitCompleted = firstCompleted.Wait(millisecondsTimeout, cancellationToken);
if (waitCompleted)
{
- Contract.Assert(firstCompleted.Status == TaskStatus.RanToCompletion);
+ Debug.Assert(firstCompleted.Status == TaskStatus.RanToCompletion);
signaledTaskIndex = Array.IndexOf(tasks, firstCompleted.Result);
- Contract.Assert(signaledTaskIndex >= 0);
+ Debug.Assert(signaledTaskIndex >= 0);
}
}
@@ -5521,7 +5508,7 @@ namespace System.Threading.Tasks
var task = new Task<TResult>();
bool succeeded = task.TrySetException(exception);
- Contract.Assert(succeeded, "This should always succeed on a new task.");
+ Debug.Assert(succeeded, "This should always succeed on a new task.");
return task;
}
@@ -5559,7 +5546,7 @@ namespace System.Threading.Tasks
var task = new Task<TResult>();
bool succeeded = task.TrySetCanceled(exception.CancellationToken, exception);
- Contract.Assert(succeeded, "This should always succeed on a new task.");
+ Debug.Assert(succeeded, "This should always succeed on a new task.");
return task;
}
@@ -6124,7 +6111,7 @@ namespace System.Threading.Tasks
for (int i = 0; i < m_tasks.Length; i++)
{
var task = m_tasks[i];
- Contract.Assert(task != null, "Constituent task in WhenAll should never be null");
+ Debug.Assert(task != null, "Constituent task in WhenAll should never be null");
if (task.IsFaulted)
{
@@ -6144,7 +6131,7 @@ namespace System.Threading.Tasks
if (observedExceptions != null)
{
- Contract.Assert(observedExceptions.Count > 0, "Expected at least one exception");
+ Debug.Assert(observedExceptions.Count > 0, "Expected at least one exception");
//We don't need to TraceOperationCompleted here because TrySetException will call Finish and we'll log it there
@@ -6166,7 +6153,7 @@ namespace System.Threading.Tasks
TrySetResult(default(VoidTaskResult));
}
}
- Contract.Assert(m_count >= 0, "Count should never go below 0");
+ Debug.Assert(m_count >= 0, "Count should never go below 0");
}
public bool InvokeMayRunArbitraryCode { get { return true; } }
@@ -6371,7 +6358,7 @@ namespace System.Threading.Tasks
for (int i = 0; i < m_tasks.Length; i++)
{
Task<T> task = m_tasks[i];
- Contract.Assert(task != null, "Constituent task in WhenAll should never be null");
+ Debug.Assert(task != null, "Constituent task in WhenAll should never be null");
if (task.IsFaulted)
{
@@ -6384,7 +6371,7 @@ namespace System.Threading.Tasks
}
else
{
- Contract.Assert(task.Status == TaskStatus.RanToCompletion);
+ Debug.Assert(task.Status == TaskStatus.RanToCompletion);
results[i] = task.GetResultCore(waitCompletionNotification: false); // avoid Result, which would triggering debug notification
}
@@ -6396,7 +6383,7 @@ namespace System.Threading.Tasks
if (observedExceptions != null)
{
- Contract.Assert(observedExceptions.Count > 0, "Expected at least one exception");
+ Debug.Assert(observedExceptions.Count > 0, "Expected at least one exception");
//We don't need to TraceOperationCompleted here because TrySetException will call Finish and we'll log it there
@@ -6418,7 +6405,7 @@ namespace System.Threading.Tasks
TrySetResult(results);
}
}
- Contract.Assert(m_count >= 0, "Count should never go below 0");
+ Debug.Assert(m_count >= 0, "Count should never go below 0");
}
public bool InvokeMayRunArbitraryCode { get { return true; } }
@@ -6612,7 +6599,7 @@ namespace System.Threading.Tasks
Task continuationTask = continuationObject as Task;
if (continuationTask != null)
{
- Contract.Assert(continuationTask.m_action == null);
+ Debug.Assert(continuationTask.m_action == null);
Delegate[] delegates = continuationTask.GetDelegateContinuationsForDebugger();
if (delegates != null)
return delegates;
@@ -6677,13 +6664,11 @@ namespace System.Threading.Tasks
m_completingTask = completingTask;
}
- [SecurityCritical]
void IThreadPoolWorkItem.ExecuteWorkItem()
{
m_action.Invoke(m_completingTask);
}
- [SecurityCritical]
void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae)
{
/* NOP */
@@ -6999,25 +6984,12 @@ namespace System.Threading.Tasks
// that can SO in 20 inlines on a typical 1MB stack size probably needs to be revisited anyway.
private const int MAX_UNCHECKED_INLINING_DEPTH = 20;
-#if !FEATURE_CORECLR
-
- private UInt64 m_lastKnownWatermark;
- private static int s_pageSize;
-
- // We are conservative here. We assume that the platform needs a whole 64KB to
- // respond to stack overflow. This means that for very small stacks (e.g. 128KB)
- // we'll fail a lot of stack checks incorrectly.
- private const long STACK_RESERVED_SPACE = 4096 * 16;
-
-#endif // !FEATURE_CORECLR
-
/// <summary>
/// This method needs to be called before attempting inline execution on the current thread.
/// If false is returned, it means we are too close to the end of the stack and should give up inlining.
/// Each call to TryBeginInliningScope() that returns true must be matched with a
/// call to EndInliningScope() regardless of whether inlining actually took place.
/// </summary>
- [SecuritySafeCritical]
internal bool TryBeginInliningScope()
{
// If we're still under the 'safe' limit we'll just skip the stack probe to save p/invoke calls
@@ -7037,59 +7009,15 @@ namespace System.Threading.Tasks
internal void EndInliningScope()
{
m_inliningDepth--;
- Contract.Assert(m_inliningDepth >= 0, "Inlining depth count should never go negative.");
+ Debug.Assert(m_inliningDepth >= 0, "Inlining depth count should never go negative.");
// do the right thing just in case...
if (m_inliningDepth < 0) m_inliningDepth = 0;
}
- [SecurityCritical]
private unsafe bool CheckForSufficientStack()
{
-#if FEATURE_CORECLR
return RuntimeHelpers.TryEnsureSufficientExecutionStack();
-#else
- // see if we already have the system page size info recorded
- int pageSize = s_pageSize;
- if (pageSize == 0)
- {
- // If not we need to query it from GetSystemInfo()
- // Note that this happens only once for the process lifetime
- Win32Native.SYSTEM_INFO sysInfo = new Win32Native.SYSTEM_INFO();
- Win32Native.GetSystemInfo(ref sysInfo);
-
- s_pageSize = pageSize = sysInfo.dwPageSize;
- }
-
- Win32Native.MEMORY_BASIC_INFORMATION stackInfo = new Win32Native.MEMORY_BASIC_INFORMATION();
-
- // We subtract one page for our request. VirtualQuery rounds UP to the next page.
- // Unfortunately, the stack grows down. If we're on the first page (last page in the
- // VirtualAlloc), we'll be moved to the next page, which is off the stack!
-
- UIntPtr currentAddr = new UIntPtr(&stackInfo - pageSize);
- UInt64 current64 = currentAddr.ToUInt64();
-
- // Check whether we previously recorded a deeper stack than where we currently are,
- // If so we don't need to do the P/Invoke to VirtualQuery
- if (m_lastKnownWatermark != 0 && current64 > m_lastKnownWatermark)
- return true;
-
- // Actual stack probe. P/Invoke to query for the current stack allocation information.
- Win32Native.VirtualQuery(currentAddr.ToPointer(), ref stackInfo, (UIntPtr)(sizeof(Win32Native.MEMORY_BASIC_INFORMATION)));
-
- // If the current address minus the base (remember: the stack grows downward in the
- // address space) is greater than the number of bytes requested plus the reserved
- // space at the end, the request has succeeded.
-
- if ((current64 - ((UIntPtr)stackInfo.AllocationBase).ToUInt64()) > STACK_RESERVED_SPACE)
- {
- m_lastKnownWatermark = current64;
- return true;
- }
-
- return false;
-#endif
}
}
@@ -7204,16 +7132,15 @@ namespace System.Threading.Tasks
case STATE_WAITING_ON_INNER_TASK:
bool result = TrySetFromTask(completingTask, lookForOce: false);
_state = STATE_DONE; // bump the state
- Contract.Assert(result, "Expected TrySetFromTask from inner task to succeed");
+ Debug.Assert(result, "Expected TrySetFromTask from inner task to succeed");
break;
default:
- Contract.Assert(false, "UnwrapPromise in illegal state");
+ Debug.Assert(false, "UnwrapPromise in illegal state");
break;
}
}
// Calls InvokeCore asynchronously.
- [SecuritySafeCritical]
private void InvokeCoreAsync(Task completingTask)
{
// Queue a call to Invoke. If we're so deep on the stack that we're at risk of overflowing,
@@ -7233,7 +7160,7 @@ namespace System.Threading.Tasks
private void ProcessCompletedOuterTask(Task task)
{
Contract.Requires(task != null && task.IsCompleted, "Expected non-null, completed outer task");
- Contract.Assert(_state == STATE_WAITING_ON_OUTER_TASK, "We're in the wrong state!");
+ Debug.Assert(_state == STATE_WAITING_ON_OUTER_TASK, "We're in the wrong state!");
// Bump our state before proceeding any further
_state = STATE_WAITING_ON_INNER_TASK;
@@ -7245,7 +7172,7 @@ namespace System.Threading.Tasks
case TaskStatus.Canceled:
case TaskStatus.Faulted:
bool result = TrySetFromTask(task, _lookForOce);
- Contract.Assert(result, "Expected TrySetFromTask from outer task to succeed");
+ Debug.Assert(result, "Expected TrySetFromTask from outer task to succeed");
break;
// Otherwise, process the inner task it returned.