Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs')
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs370
1 files changed, 149 insertions, 221 deletions
diff --git a/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs b/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs
index 30302b936..9dbc0db08 100644
--- a/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs
@@ -1,15 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#pragma warning disable 0420
-
-//
-
-////////////////////////////////////////////////////////////////////////////////
using System.Collections.Generic;
using System.Diagnostics;
-using System.Runtime.InteropServices;
namespace System.Threading
{
@@ -33,46 +27,44 @@ namespace System.Threading
/// </remarks>
public class CancellationTokenSource : IDisposable
{
- //static sources that can be used as the backing source for 'fixed' CancellationTokens that never change state.
- private static readonly CancellationTokenSource _staticSource_Set = new CancellationTokenSource(true);
- private static readonly CancellationTokenSource _staticSource_NotCancelable = new CancellationTokenSource(false);
+ // static sources that can be used as the backing source for 'fixed' CancellationTokens that never change state.
+ internal static readonly CancellationTokenSource s_canceledSource = new CancellationTokenSource() { _state = NotifyingCompleteState };
+ internal static readonly CancellationTokenSource s_neverCanceledSource = new CancellationTokenSource() { _state = CannotBeCanceled };
- //Note: the callback lists array is only created on first registration.
- // the actual callback lists are only created on demand.
- // Storing a registered callback costs around >60bytes, hence some overhead for the lists array is OK
+ // Note: the callback lists array is only created on first registration.
+ // the actual callback lists are only created on demand.
+ // Storing a registered callback costs around >60bytes, hence some overhead for the lists array is OK
// At most 24 lists seems reasonable, and caps the cost of the listsArray to 96bytes(32-bit,24-way) or 192bytes(64-bit,24-way).
private static readonly int s_nLists = (PlatformHelper.ProcessorCount > 24) ? 24 : PlatformHelper.ProcessorCount;
- private volatile ManualResetEvent m_kernelEvent; //lazily initialized if required.
+ private volatile ManualResetEvent _kernelEvent; //lazily initialized if required.
- private volatile SparselyPopulatedArray<CancellationCallbackInfo>[] m_registeredCallbacksLists;
+ private volatile SparselyPopulatedArray<CancellationCallbackInfo>[] _registeredCallbacksLists;
- // legal values for m_state
- private const int CANNOT_BE_CANCELED = 0;
- private const int NOT_CANCELED = 1;
- private const int NOTIFYING = 2;
- private const int NOTIFYINGCOMPLETE = 3;
+ // legal values for _state
+ private const int CannotBeCanceled = 0;
+ private const int NotCanceledState = 1;
+ private const int NotifyingState = 2;
+ private const int NotifyingCompleteState = 3;
- //m_state uses the pattern "volatile int32 reads, with cmpxch writes" which is safe for updates and cannot suffer torn reads.
- private volatile int m_state;
+ //_state uses the pattern "volatile int32 reads, with cmpxch writes" which is safe for updates and cannot suffer torn reads.
+ private volatile int _state;
+ /// <summary>The ID of the thread currently executing the main body of CTS.Cancel()</summary>
+ /// <remarks>
+ /// This helps us to know if a call to ctr.Dispose() is running 'within' a cancellation callback.
+ /// This is updated as we move between the main thread calling cts.Cancel() and any syncContexts
+ /// that are used to actually run the callbacks.
+ /// </remarks>
+ private volatile int _threadIDExecutingCallbacks = -1;
- /// The ID of the thread currently executing the main body of CTS.Cancel()
- /// this helps us to know if a call to ctr.Dispose() is running 'within' a cancellation callback.
- /// This is updated as we move between the main thread calling cts.Cancel() and any syncContexts that are used to
- /// actually run the callbacks.
- private volatile int m_threadIDExecutingCallbacks = -1;
-
- private bool m_disposed;
+ private bool _disposed;
// we track the running callback to assist ctr.Dispose() to wait for the target callback to complete.
- private volatile CancellationCallbackInfo m_executingCallback;
+ private volatile CancellationCallbackInfo _executingCallback;
// provided for CancelAfter and timer-related constructors
- private volatile Timer m_timer;
-
- // ----------------------
- // ** public properties
+ private volatile Timer _timer;
/// <summary>
/// Gets whether cancellation has been requested for this <see
@@ -94,34 +86,25 @@ namespace System.Threading
/// canceled concurrently.
/// </para>
/// </remarks>
- public bool IsCancellationRequested
- {
- get { return m_state >= NOTIFYING; }
- }
+ public bool IsCancellationRequested => _state >= NotifyingState;
/// <summary>
/// A simple helper to determine whether cancellation has finished.
/// </summary>
- internal bool IsCancellationCompleted
- {
- get { return m_state == NOTIFYINGCOMPLETE; }
- }
+ internal bool IsCancellationCompleted => _state == NotifyingCompleteState;
/// <summary>
/// A simple helper to determine whether disposal has occurred.
/// </summary>
- internal bool IsDisposed
- {
- get { return m_disposed; }
- }
+ internal bool IsDisposed => _disposed;
/// <summary>
/// The ID of the thread that is running callbacks.
/// </summary>
internal int ThreadIDExecutingCallbacks
{
- set { m_threadIDExecutingCallbacks = value; }
- get { return m_threadIDExecutingCallbacks; }
+ get => _threadIDExecutingCallbacks;
+ set => _threadIDExecutingCallbacks = value;
}
/// <summary>
@@ -140,36 +123,25 @@ namespace System.Threading
return new CancellationToken(this);
}
}
-
- // ----------------------
- // ** internal and private properties.
-
- /// <summary>
- ///
- /// </summary>
internal bool CanBeCanceled
{
- get { return m_state != CANNOT_BE_CANCELED; }
+ get { return _state != CannotBeCanceled; }
}
-
- /// <summary>
- ///
- /// </summary>
internal WaitHandle WaitHandle
{
get
{
ThrowIfDisposed();
- // fast path if already allocated.
- if (m_kernelEvent != null)
- return m_kernelEvent;
+ // Return the handle if it was already allocated.
+ if (_kernelEvent != null)
+ return _kernelEvent;
- // lazy-init the mre.
+ // Lazily-initialize the handle.
ManualResetEvent mre = new ManualResetEvent(false);
- if (Interlocked.CompareExchange(ref m_kernelEvent, mre, null) != null)
+ if (Interlocked.CompareExchange(ref _kernelEvent, mre, null) != null)
{
- ((IDisposable)mre).Dispose();
+ mre.Dispose();
}
// There is a race condition between checking IsCancellationRequested and setting the event.
@@ -177,9 +149,9 @@ namespace System.Threading
// 1. if IsCancellationRequested = true, then we will call Set()
// 2. if IsCancellationRequested = false, then NotifyCancellation will see that the event exists, and will call Set().
if (IsCancellationRequested)
- m_kernelEvent.Set();
+ _kernelEvent.Set();
- return m_kernelEvent;
+ return _kernelEvent;
}
}
@@ -187,10 +159,7 @@ namespace System.Threading
/// <summary>
/// The currently executing callback
/// </summary>
- internal CancellationCallbackInfo ExecutingCallback
- {
- get { return m_executingCallback; }
- }
+ internal CancellationCallbackInfo ExecutingCallback => _executingCallback;
#if DEBUG
/// <summary>
@@ -202,7 +171,7 @@ namespace System.Threading
{
get
{
- SparselyPopulatedArray<CancellationCallbackInfo>[] callbackLists = m_registeredCallbacksLists;
+ SparselyPopulatedArray<CancellationCallbackInfo>[] callbackLists = _registeredCallbacksLists;
if (callbackLists == null)
return 0;
@@ -227,23 +196,10 @@ namespace System.Threading
}
#endif
- // ** Public Constructors
-
/// <summary>
/// Initializes the <see cref="T:System.Threading.CancellationTokenSource"/>.
/// </summary>
- public CancellationTokenSource()
- {
- m_state = NOT_CANCELED;
- }
-
- // ** Private constructors for static sources.
- // set=false ==> cannot be canceled.
- // set=true ==> is canceled.
- private CancellationTokenSource(bool set)
- {
- m_state = set ? NOTIFYINGCOMPLETE : CANNOT_BE_CANCELED;
- }
+ public CancellationTokenSource() => _state = NotCanceledState;
/// <summary>
/// Constructs a <see cref="T:System.Threading.CancellationTokenSource"/> that will be canceled after a specified time span.
@@ -267,7 +223,7 @@ namespace System.Threading
public CancellationTokenSource(TimeSpan delay)
{
long totalMilliseconds = (long)delay.TotalMilliseconds;
- if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
{
throw new ArgumentOutOfRangeException(nameof(delay));
}
@@ -294,7 +250,7 @@ namespace System.Threading
/// canceled already.
/// </para>
/// </remarks>
- public CancellationTokenSource(Int32 millisecondsDelay)
+ public CancellationTokenSource(int millisecondsDelay)
{
if (millisecondsDelay < -1)
{
@@ -305,14 +261,12 @@ namespace System.Threading
}
// Common initialization logic when constructing a CTS with a delay parameter
- private void InitializeWithTimer(Int32 millisecondsDelay)
+ private void InitializeWithTimer(int millisecondsDelay)
{
- m_state = NOT_CANCELED;
- m_timer = new Timer(s_timerCallback, this, millisecondsDelay, -1);
+ _state = NotCanceledState;
+ _timer = new Timer(s_timerCallback, this, millisecondsDelay, -1);
}
- // ** Public Methods
-
/// <summary>
/// Communicates a request for cancellation.
/// </summary>
@@ -334,10 +288,7 @@ namespace System.Threading
/// by the registered callbacks on the associated <see cref="T:System.Threading.CancellationToken"/>.</exception>
/// <exception cref="T:System.ObjectDisposedException">This <see
/// cref="T:System.Threading.CancellationTokenSource"/> has been disposed.</exception>
- public void Cancel()
- {
- Cancel(false);
- }
+ public void Cancel() => Cancel(false);
/// <summary>
/// Communicates a request for cancellation.
@@ -391,14 +342,13 @@ namespace System.Threading
/// </para>
/// <para>
/// Subsequent calls to CancelAfter will reset the delay for this
- /// <see cref="T:System.Threading.CancellationTokenSource"/>, if it has not been
- /// canceled already.
+ /// <see cref="T:System.Threading.CancellationTokenSource"/>, if it has not been canceled already.
/// </para>
/// </remarks>
public void CancelAfter(TimeSpan delay)
{
long totalMilliseconds = (long)delay.TotalMilliseconds;
- if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
{
throw new ArgumentOutOfRangeException(nameof(delay));
}
@@ -430,7 +380,7 @@ namespace System.Threading
/// canceled already.
/// </para>
/// </remarks>
- public void CancelAfter(Int32 millisecondsDelay)
+ public void CancelAfter(int millisecondsDelay)
{
ThrowIfDisposed();
@@ -439,7 +389,10 @@ namespace System.Threading
throw new ArgumentOutOfRangeException(nameof(millisecondsDelay));
}
- if (IsCancellationRequested) return;
+ if (IsCancellationRequested)
+ {
+ return;
+ }
// There is a race condition here as a Cancel could occur between the check of
// IsCancellationRequested and the creation of the timer. This is benign; in the
@@ -450,26 +403,25 @@ namespace System.Threading
// expired and Disposed itself). But this would be considered bad behavior, as
// Dispose() is not thread-safe and should not be called concurrently with CancelAfter().
- if (m_timer == null)
+ if (_timer == null)
{
// Lazily initialize the timer in a thread-safe fashion.
// Initially set to "never go off" because we don't want to take a
// chance on a timer "losing" the initialization and then
// cancelling the token before it (the timer) can be disposed.
Timer newTimer = new Timer(s_timerCallback, this, -1, -1);
- if (Interlocked.CompareExchange(ref m_timer, newTimer, null) != null)
+ if (Interlocked.CompareExchange(ref _timer, newTimer, null) != null)
{
// We did not initialize the timer. Dispose the new timer.
newTimer.Dispose();
}
}
-
- // It is possible that m_timer has already been disposed, so we must do
+ // It is possible that _timer has already been disposed, so we must do
// the following in a try/catch block.
try
{
- m_timer.Change(millisecondsDelay, -1);
+ _timer.Change(millisecondsDelay, -1);
}
catch (ObjectDisposedException)
{
@@ -495,7 +447,7 @@ namespace System.Threading
// against this race condition.
try
{
- cts.Cancel(); // will take care of disposing of m_timer
+ cts.Cancel(); // will take care of disposing of _timer
}
catch (ObjectDisposedException)
{
@@ -523,11 +475,9 @@ namespace System.Threading
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
- // There is nothing to do if disposing=false because the CancellationTokenSource holds no unmanaged resources.
-
- if (disposing && !m_disposed)
+ if (disposing && !_disposed)
{
- //NOTE: We specifically tolerate that a callback can be deregistered
+ //NOTE: We specifically tolerate that a callback can be unregistered
// after the CTS has been disposed and/or concurrently with cts.Dispose().
// This is safe without locks because the reg.Dispose() only
// mutates a sparseArrayFragment and then reads from properties of the CTS that are not
@@ -535,8 +485,8 @@ namespace System.Threading
//
// We also tolerate that a callback can be registered after the CTS has been
// disposed. This is safe without locks because InternalRegister is tolerant
- // of m_registeredCallbacksLists becoming null during its execution. However,
- // we run the acceptable risk of m_registeredCallbacksLists getting reinitialized
+ // of _registeredCallbacksLists becoming null during its execution. However,
+ // we run the acceptable risk of _registeredCallbacksLists getting reinitialized
// to non-null if there is a race between Dispose and Register, in which case this
// instance may unnecessarily hold onto a registered callback. But that's no worse
// than if Dispose wasn't safe to use concurrently, as Dispose would never be called,
@@ -549,57 +499,43 @@ namespace System.Threading
// internal source of cancellation, then Disposes of that linked source, which could
// happen at the same time the external entity is requesting cancellation).
- m_timer?.Dispose(); // Timer.Dispose is thread-safe
+ _timer?.Dispose(); // Timer.Dispose is thread-safe
// registered callbacks are now either complete or will never run, due to guarantees made by ctr.Dispose()
// so we can now perform main disposal work without risk of linking callbacks trying to use this CTS.
- m_registeredCallbacksLists = null; // free for GC; Cancel correctly handles a null field
+ _registeredCallbacksLists = null; // free for GC; Cancel correctly handles a null field
// If a kernel event was created via WaitHandle, we'd like to Dispose of it. However,
// we only want to do so if it's not being used by Cancel concurrently. First, we
// interlocked exchange it to be null, and then we check whether cancellation is currently
// in progress. NotifyCancellation will only try to set the event if it exists after it's
- // transitioned to and while it's in the NOTIFYING state.
- if (m_kernelEvent != null)
+ // transitioned to and while it's in the NotifyingState.
+ if (_kernelEvent != null)
{
- ManualResetEvent mre = Interlocked.Exchange(ref m_kernelEvent, null);
- if (mre != null && m_state != NOTIFYING)
+ ManualResetEvent mre = Interlocked.Exchange(ref _kernelEvent, null);
+ if (mre != null && _state != NotifyingState)
{
mre.Dispose();
}
}
- m_disposed = true;
+ _disposed = true;
}
}
- // -- Internal methods.
-
/// <summary>
/// Throws an exception if the source has been disposed.
/// </summary>
internal void ThrowIfDisposed()
{
- if (m_disposed)
+ if (_disposed)
ThrowObjectDisposedException();
}
- // separation enables inlining of ThrowIfDisposed
- private static void ThrowObjectDisposedException()
- {
+ /// <summary>Throws an <see cref="ObjectDisposedException"/>. Separated out from ThrowIfDisposed to help with inlining.</summary>
+ private static void ThrowObjectDisposedException() =>
throw new ObjectDisposedException(null, SR.CancellationTokenSource_Disposed);
- }
-
- /// <summary>
- /// InternalGetStaticSource()
- /// </summary>
- /// <param name="set">Whether the source should be set.</param>
- /// <returns>A static source to be shared among multiple tokens.</returns>
- internal static CancellationTokenSource InternalGetStaticSource(bool set)
- {
- return set ? _staticSource_Set : _staticSource_NotCancelable;
- }
/// <summary>
/// Registers a callback object. If cancellation has already occurred, the
@@ -625,11 +561,11 @@ namespace System.Threading
// while at the same time not paying any non-negligible overhead. The simple compromise
// is to check whether we're disposed (not volatile), and if we see we are, to return an empty
// registration, just as if CanBeCanceled was false for the check made in CancellationToken.Register.
- // If there's a race and m_disposed is false even though it's been disposed, or if the disposal request
- // comes in after this line, we simply run the minor risk of having m_registeredCallbacksLists reinitialized
+ // If there's a race and _disposed is false even though it's been disposed, or if the disposal request
+ // comes in after this line, we simply run the minor risk of having _registeredCallbacksLists reinitialized
// (after it was cleared to null during Dispose).
- if (m_disposed)
+ if (_disposed)
return new CancellationTokenRegistration();
int myIndex = Environment.CurrentManagedThreadId % s_nLists;
@@ -639,11 +575,11 @@ namespace System.Threading
new CancellationCallbackInfo(callback, stateForCallback, executionContext, this);
//allocate the callback list array
- var registeredCallbacksLists = m_registeredCallbacksLists;
+ var registeredCallbacksLists = _registeredCallbacksLists;
if (registeredCallbacksLists == null)
{
SparselyPopulatedArray<CancellationCallbackInfo>[] list = new SparselyPopulatedArray<CancellationCallbackInfo>[s_nLists];
- registeredCallbacksLists = Interlocked.CompareExchange(ref m_registeredCallbacksLists, list, null);
+ registeredCallbacksLists = Interlocked.CompareExchange(ref _registeredCallbacksLists, list, null);
if (registeredCallbacksLists == null) registeredCallbacksLists = list;
}
@@ -665,9 +601,9 @@ namespace System.Threading
// If a cancellation has since come in, we will try to undo the registration and run the callback ourselves.
// (this avoids leaving the callback orphaned)
- bool deregisterOccurred = registration.TryDeregister();
+ bool unregisterOccurred = registration.Unregister();
- if (!deregisterOccurred)
+ if (!unregisterOccurred)
{
// The thread that is running Cancel() snagged our callback for execution.
// So we don't need to run it, but we do return the registration so that
@@ -681,29 +617,22 @@ namespace System.Threading
return new CancellationTokenRegistration();
}
- /// <summary>
- ///
- /// </summary>
private void NotifyCancellation(bool throwOnFirstException)
{
- // fast-path test to check if Notify has been called previously
- if (IsCancellationRequested)
- return;
-
// If we're the first to signal cancellation, do the main extra work.
- if (Interlocked.CompareExchange(ref m_state, NOTIFYING, NOT_CANCELED) == NOT_CANCELED)
+ if (!IsCancellationRequested && Interlocked.CompareExchange(ref _state, NotifyingState, NotCanceledState) == NotCanceledState)
{
// Dispose of the timer, if any. Dispose may be running concurrently here, but Timer.Dispose is thread-safe.
- m_timer?.Dispose();
+ _timer?.Dispose();
// Record the threadID being used for running the callbacks.
ThreadIDExecutingCallbacks = Environment.CurrentManagedThreadId;
// Set the event if it's been lazily initialized and hasn't yet been disposed of. Dispose may
- // be running concurrently, in which case either it'll have set m_kernelEvent back to null and
+ // be running concurrently, in which case either it'll have set _kernelEvent back to null and
// we won't see it here, or it'll see that we've transitioned to NOTIFYING and will skip disposing it,
// leaving cleanup to finalization.
- m_kernelEvent?.Set(); // update the MRE value.
+ _kernelEvent?.Set(); // update the MRE value.
// - late enlisters to the Canceled event will have their callbacks called immediately in the Register() methods.
// - Callbacks are not called inside a lock.
@@ -728,13 +657,13 @@ namespace System.Threading
// Design decision: call the delegates in LIFO order so that callbacks fire 'deepest first'.
// This is intended to help with nesting scenarios so that child enlisters cancel before their parents.
LowLevelListWithIList<Exception> exceptionList = null;
- SparselyPopulatedArray<CancellationCallbackInfo>[] callbackLists = m_registeredCallbacksLists;
+ SparselyPopulatedArray<CancellationCallbackInfo>[] callbackLists = _registeredCallbacksLists;
// If there are no callbacks to run, we can safely exit. Any race conditions to lazy initialize it
// will see IsCancellationRequested and will then run the callback themselves.
if (callbackLists == null)
{
- Interlocked.Exchange(ref m_state, NOTIFYINGCOMPLETE);
+ Interlocked.Exchange(ref _state, NotifyingCompleteState);
return;
}
@@ -758,8 +687,8 @@ namespace System.Threading
// 3. execute the callback
// re:#2 we do the remove on the syncCtx so that we can be sure we have control of the syncCtx before
// grabbing the callback. This prevents a deadlock if ctr.Dispose() might run on the syncCtx too.
- m_executingCallback = currArrayFragment[i];
- if (m_executingCallback != null)
+ _executingCallback = currArrayFragment[i];
+ if (_executingCallback != null)
{
//Transition to the target sync context (if necessary), and continue our work there.
CancellationCallbackCoreWorkArguments args = new CancellationCallbackCoreWorkArguments(currArrayFragment, i);
@@ -768,7 +697,7 @@ namespace System.Threading
// We assume that syncCtx.Send() has forwarded on user exceptions when appropriate.
try
{
- var wsc = m_executingCallback as CancellationCallbackInfo.WithSyncContext;
+ var wsc = _executingCallback as CancellationCallbackInfo.WithSyncContext;
if (wsc != null)
{
Debug.Assert(wsc.TargetSyncContext != null, "Should only have derived CCI if non-null SyncCtx");
@@ -801,14 +730,14 @@ namespace System.Threading
}
finally
{
- m_state = NOTIFYINGCOMPLETE;
- m_executingCallback = null;
+ _state = NotifyingCompleteState;
+ _executingCallback = null;
Interlocked.MemoryBarrier(); // for safety, prevent reorderings crossing this point and seeing inconsistent state.
}
if (exceptionList != null)
{
- Debug.Assert(exceptionList.Count > 0, "Expected exception count > 0");
+ Debug.Assert(exceptionList.Count > 0, $"Expected {exceptionList.Count} > 0");
throw new AggregateException(exceptionList);
}
}
@@ -823,15 +752,14 @@ namespace System.Threading
{
// remove the intended callback..and ensure that it worked.
// otherwise the callback has disappeared in the interim and we can immediately return.
- CancellationCallbackInfo callback = args.m_currArrayFragment.SafeAtomicRemove(args.m_currArrayIndex, m_executingCallback);
- if (callback == m_executingCallback)
+ CancellationCallbackInfo callback = args._currArrayFragment.SafeAtomicRemove(args._currArrayIndex, _executingCallback);
+ if (callback == _executingCallback)
{
callback.CancellationTokenSource.ThreadIDExecutingCallbacks = Environment.CurrentManagedThreadId;
callback.ExecuteCallback();
}
}
-
/// <summary>
/// Creates a <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> that will be in the canceled state
/// when any of the source tokens are in the canceled state.
@@ -906,7 +834,7 @@ namespace System.Threading
protected override void Dispose(bool disposing)
{
- if (!disposing || m_disposed) return;
+ if (!disposing || _disposed) return;
_reg1.Dispose();
base.Dispose(disposing);
}
@@ -925,7 +853,7 @@ namespace System.Threading
protected override void Dispose(bool disposing)
{
- if (!disposing || m_disposed) return;
+ if (!disposing || _disposed) return;
_reg1.Dispose();
_reg2.Dispose();
base.Dispose(disposing);
@@ -936,17 +864,17 @@ namespace System.Threading
{
internal static readonly Action<object> s_linkedTokenCancelDelegate =
s => ((CancellationTokenSource)s).NotifyCancellation(throwOnFirstException: false); // skip ThrowIfDisposed() check in Cancel()
- private CancellationTokenRegistration[] m_linkingRegistrations;
+ private CancellationTokenRegistration[] _linkingRegistrations;
internal LinkedNCancellationTokenSource(params CancellationToken[] tokens)
{
- m_linkingRegistrations = new CancellationTokenRegistration[tokens.Length];
+ _linkingRegistrations = new CancellationTokenRegistration[tokens.Length];
for (int i = 0; i < tokens.Length; i++)
{
if (tokens[i].CanBeCanceled)
{
- m_linkingRegistrations[i] = tokens[i].InternalRegisterWithoutEC(s_linkedTokenCancelDelegate, this);
+ _linkingRegistrations[i] = tokens[i].InternalRegisterWithoutEC(s_linkedTokenCancelDelegate, this);
}
// Empty slots in the array will be default(CancellationTokenRegistration), which are nops to Dispose.
// Based on usage patterns, such occurrences should also be rare, such that it's not worth resizing
@@ -956,13 +884,13 @@ namespace System.Threading
protected override void Dispose(bool disposing)
{
- if (!disposing || m_disposed)
+ if (!disposing || _disposed)
return;
- CancellationTokenRegistration[] linkingRegistrations = m_linkingRegistrations;
+ CancellationTokenRegistration[] linkingRegistrations = _linkingRegistrations;
if (linkingRegistrations != null)
{
- m_linkingRegistrations = null; // release for GC once we're done enumerating
+ _linkingRegistrations = null; // release for GC once we're done enumerating
for (int i = 0; i < linkingRegistrations.Length; i++)
{
linkingRegistrations[i].Dispose();
@@ -980,13 +908,13 @@ namespace System.Threading
// Helper struct for passing data to the target sync context
internal struct CancellationCallbackCoreWorkArguments
{
- internal SparselyPopulatedArrayFragment<CancellationCallbackInfo> m_currArrayFragment;
- internal int m_currArrayIndex;
+ internal SparselyPopulatedArrayFragment<CancellationCallbackInfo> _currArrayFragment;
+ internal int _currArrayIndex;
public CancellationCallbackCoreWorkArguments(SparselyPopulatedArrayFragment<CancellationCallbackInfo> currArrayFragment, int currArrayIndex)
{
- m_currArrayFragment = currArrayFragment;
- m_currArrayIndex = currArrayIndex;
+ _currArrayFragment = currArrayFragment;
+ _currArrayIndex = currArrayIndex;
}
}
@@ -1078,8 +1006,8 @@ namespace System.Threading
/// <typeparam name="T">The kind of elements contained within.</typeparam>
internal class SparselyPopulatedArray<T> where T : class
{
- private readonly SparselyPopulatedArrayFragment<T> m_head;
- private volatile SparselyPopulatedArrayFragment<T> m_tail;
+ private readonly SparselyPopulatedArrayFragment<T> _head;
+ private volatile SparselyPopulatedArrayFragment<T> _tail;
/// <summary>
/// Allocates a new array with the given initial size.
@@ -1087,7 +1015,7 @@ namespace System.Threading
/// <param name="initialSize">How many array slots to pre-allocate.</param>
internal SparselyPopulatedArray(int initialSize)
{
- m_head = m_tail = new SparselyPopulatedArrayFragment<T>(initialSize);
+ _head = _tail = new SparselyPopulatedArrayFragment<T>(initialSize);
}
#if DEBUG
@@ -1097,7 +1025,7 @@ namespace System.Threading
/// </summary>
internal SparselyPopulatedArrayFragment<T> Head
{
- get { return m_head; }
+ get { return _head; }
}
#endif
@@ -1106,7 +1034,7 @@ namespace System.Threading
/// </summary>
internal SparselyPopulatedArrayFragment<T> Tail
{
- get { return m_tail; }
+ get { return _tail; }
}
/// <summary>
@@ -1114,36 +1042,36 @@ namespace System.Threading
/// If no slots are available, the array is grown. The method doesn't return until successful.
/// </summary>
/// <param name="element">The element to add.</param>
- /// <returns>Information about where the add happened, to enable O(1) deregistration.</returns>
+ /// <returns>Information about where the add happened, to enable O(1) unregistration.</returns>
internal SparselyPopulatedArrayAddInfo<T> Add(T element)
{
while (true)
{
// Get the tail, and ensure it's up to date.
- SparselyPopulatedArrayFragment<T> tail = m_tail;
- while (tail.m_next != null)
- m_tail = (tail = tail.m_next);
+ SparselyPopulatedArrayFragment<T> tail = _tail;
+ while (tail._next != null)
+ _tail = (tail = tail._next);
// Search for a free index, starting from the tail.
SparselyPopulatedArrayFragment<T> curr = tail;
while (curr != null)
{
const int RE_SEARCH_THRESHOLD = -10; // Every 10 skips, force a search.
- if (curr.m_freeCount < 1)
- --curr.m_freeCount;
+ if (curr._freeCount < 1)
+ --curr._freeCount;
- if (curr.m_freeCount > 0 || curr.m_freeCount < RE_SEARCH_THRESHOLD)
+ if (curr._freeCount > 0 || curr._freeCount < RE_SEARCH_THRESHOLD)
{
int c = curr.Length;
// We'll compute a start offset based on how many free slots we think there
- // are. This optimizes for ordinary the LIFO deregistration pattern, and is
+ // are. This optimizes for ordinary the LIFO unregistration pattern, and is
// far from perfect due to the non-threadsafe ++ and -- of the free counter.
- int start = ((c - curr.m_freeCount) % c);
+ int start = ((c - curr._freeCount) % c);
if (start < 0)
{
start = 0;
- curr.m_freeCount--; // Too many free elements; fix up.
+ curr._freeCount--; // Too many free elements; fix up.
}
Debug.Assert(start >= 0 && start < c, "start is outside of bounds");
@@ -1152,29 +1080,29 @@ namespace System.Threading
{
// If the slot is null, try to CAS our element into it.
int tryIndex = (start + i) % c;
- Debug.Assert(tryIndex >= 0 && tryIndex < curr.m_elements.Length, "tryIndex is outside of bounds");
+ Debug.Assert(tryIndex >= 0 && tryIndex < curr._elements.Length, "tryIndex is outside of bounds");
- if (curr.m_elements[tryIndex] == null && Interlocked.CompareExchange(ref curr.m_elements[tryIndex], element, null) == null)
+ if (curr._elements[tryIndex] == null && Interlocked.CompareExchange(ref curr._elements[tryIndex], element, null) == null)
{
// We adjust the free count by --. Note: if this drops to 0, we will skip
// the fragment on the next search iteration. Searching threads will -- the
// count and force a search every so often, just in case fragmentation occurs.
- int newFreeCount = curr.m_freeCount - 1;
- curr.m_freeCount = newFreeCount > 0 ? newFreeCount : 0;
+ int newFreeCount = curr._freeCount - 1;
+ curr._freeCount = newFreeCount > 0 ? newFreeCount : 0;
return new SparselyPopulatedArrayAddInfo<T>(curr, tryIndex);
}
}
}
- curr = curr.m_prev;
+ curr = curr._prev;
}
// If we got here, we need to add a new chunk to the tail and try again.
SparselyPopulatedArrayFragment<T> newTail = new SparselyPopulatedArrayFragment<T>(
- tail.m_elements.Length == 4096 ? 4096 : tail.m_elements.Length * 2, tail);
- if (Interlocked.CompareExchange(ref tail.m_next, newTail, null) == null)
+ tail._elements.Length == 4096 ? 4096 : tail._elements.Length * 2, tail);
+ if (Interlocked.CompareExchange(ref tail._next, newTail, null) == null)
{
- m_tail = newTail;
+ _tail = newTail;
}
}
}
@@ -1186,25 +1114,25 @@ namespace System.Threading
/// </summary>
internal struct SparselyPopulatedArrayAddInfo<T> where T : class
{
- private SparselyPopulatedArrayFragment<T> m_source;
- private int m_index;
+ private SparselyPopulatedArrayFragment<T> _source;
+ private int _index;
internal SparselyPopulatedArrayAddInfo(SparselyPopulatedArrayFragment<T> source, int index)
{
Debug.Assert(source != null);
Debug.Assert(index >= 0 && index < source.Length);
- m_source = source;
- m_index = index;
+ _source = source;
+ _index = index;
}
internal SparselyPopulatedArrayFragment<T> Source
{
- get { return m_source; }
+ get { return _source; }
}
internal int Index
{
- get { return m_index; }
+ get { return _index; }
}
}
@@ -1214,10 +1142,10 @@ namespace System.Threading
/// <typeparam name="T">The kind of elements contained within.</typeparam>
internal class SparselyPopulatedArrayFragment<T> where T : class
{
- internal readonly T[] m_elements; // The contents, sparsely populated (with nulls).
- internal volatile int m_freeCount; // A hint of the number of free elements.
- internal volatile SparselyPopulatedArrayFragment<T> m_next; // The next fragment in the chain.
- internal volatile SparselyPopulatedArrayFragment<T> m_prev; // The previous fragment in the chain.
+ internal readonly T[] _elements; // The contents, sparsely populated (with nulls).
+ internal volatile int _freeCount; // A hint of the number of free elements.
+ internal volatile SparselyPopulatedArrayFragment<T> _next; // The next fragment in the chain.
+ internal volatile SparselyPopulatedArrayFragment<T> _prev; // The previous fragment in the chain.
internal SparselyPopulatedArrayFragment(int size) : this(size, null)
{
@@ -1225,31 +1153,31 @@ namespace System.Threading
internal SparselyPopulatedArrayFragment(int size, SparselyPopulatedArrayFragment<T> prev)
{
- m_elements = new T[size];
- m_freeCount = size;
- m_prev = prev;
+ _elements = new T[size];
+ _freeCount = size;
+ _prev = prev;
}
internal T this[int index]
{
- get { return Volatile.Read<T>(ref m_elements[index]); }
+ get { return Volatile.Read<T>(ref _elements[index]); }
}
internal int Length
{
- get { return m_elements.Length; }
+ get { return _elements.Length; }
}
#if DEBUG
// Used in DEBUG mode by CancellationTokenSource.CallbackCount
internal SparselyPopulatedArrayFragment<T> Next
{
- get { return m_next; }
+ get { return _next; }
}
#endif
internal SparselyPopulatedArrayFragment<T> Prev
{
- get { return m_prev; }
+ get { return _prev; }
}
// only removes the item at the specified index if it is still the expected one.
@@ -1258,9 +1186,9 @@ namespace System.Threading
// otherwise the remove did not occur.
internal T SafeAtomicRemove(int index, T expectedElement)
{
- T prevailingValue = Interlocked.CompareExchange(ref m_elements[index], null, expectedElement);
+ T prevailingValue = Interlocked.CompareExchange(ref _elements[index], null, expectedElement);
if (prevailingValue != null)
- ++m_freeCount;
+ ++_freeCount;
return prevailingValue;
}
}