Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Threading / CancellationTokenRegistration.cs / 1305376 / CancellationTokenRegistration.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// [....]
////////////////////////////////////////////////////////////////////////////////
using System.Diagnostics.Contracts;
using System.Security.Permissions;
namespace System.Threading
{
///
/// Represents a callback delegate that has been registered with a CancellationToken .
///
///
/// To unregister a callback, dispose the corresponding Registration instance.
///
[HostProtection(Synchronization = true, ExternalThreading = true)]
public struct CancellationTokenRegistration : IEquatable, IDisposable
{
private readonly CancellationTokenSource m_tokenSource;
private readonly CancellationCallbackInfo m_callbackInfo;
private readonly SparselyPopulatedArrayAddInfo m_registrationInfo;
internal CancellationTokenRegistration(
CancellationTokenSource tokenSource,
CancellationCallbackInfo callbackInfo,
SparselyPopulatedArrayAddInfo registrationInfo)
{
m_tokenSource = tokenSource;
m_callbackInfo = callbackInfo;
m_registrationInfo = registrationInfo;
}
///
/// Attempts to deregister the item. If it's already being run, this may fail.
/// Entails a full memory fence.
///
/// True if the callback was found and deregistered, false otherwise.
internal bool TryDeregister()
{
if (m_registrationInfo.Source == null) //can be null for dummy registrations.
return false;
// Try to remove the callback info from the array.
// It is possible the callback info is missing (removed for run, or removed by someone else)
// It is also possible there is info in the array but it doesn't match our current registration's callback info.
CancellationCallbackInfo prevailingCallbackInfoInSlot = m_registrationInfo.Source.SafeAtomicRemove(m_registrationInfo.Index, m_callbackInfo);
if (prevailingCallbackInfoInSlot != m_callbackInfo)
return false; //the callback in the slot wasn't us.
return true;
}
///
/// Disposes of the registration and unregisters the target callback from the associated
/// CancellationToken .
/// If the target callback is currently executing this method will wait until it completes, except
/// in the degenerate cases where a callback method deregisters itself.
///
public void Dispose()
{
// If the token source has been disposed, we must throw.
if (m_tokenSource != null)
m_tokenSource.ThrowIfDisposed();
// Remove the entry from the array.
// This call includes a full memory fence which prevents potential reorderings of the reads below
bool deregisterOccured = TryDeregister();
// We guarantee that we will not return if the callback is being executed (assuming we are not currently called by the callback itself)
// We achieve this by the following rules:
// 1. if we are called in the context of an executing callback, no need to wait (determined by tracking callback-executor threadID)
// - if the currently executing callback is this CTR, then waiting would deadlock. (We choose to return rather than deadlock)
// - if not, then this CTR cannot be the one executing, hence no need to wait
//
// 2. if deregistration failed, and we are on a different thread, then the callback may be running under control of cts.Cancel()
// => poll until cts.ExecutingCallback is not the one we are trying to deregister.
if (m_tokenSource != null &&
m_tokenSource.IsCancellationRequested && //running callbacks has commenced.
! m_tokenSource.IsCancellationCompleted && //running callbacks hasn't finished
!deregisterOccured && //deregistration failed (ie the callback is missing from the list)
m_tokenSource.ThreadIDExecutingCallbacks != Thread.CurrentThread.ManagedThreadId) //the executingThreadID is not this threadID.
{
// Callback execution is in progress, the executing thread is different to us and has taken the callback for execution
// so observe and wait until this target callback is no longer the executing callback.
m_tokenSource.WaitForCallbackToComplete(m_callbackInfo);
}
}
///
/// Determines whether two CancellationTokenRegistration
/// instances are equal.
///
/// The first instance.
/// The second instance.
/// True if the instances are equal; otherwise, false.
public static bool operator ==(CancellationTokenRegistration left, CancellationTokenRegistration right)
{
return left.Equals(right);
}
///
/// Determines whether two CancellationTokenRegistration instances are not equal.
///
/// The first instance.
/// The second instance.
/// True if the instances are not equal; otherwise, false.
public static bool operator !=(CancellationTokenRegistration left, CancellationTokenRegistration right)
{
return !left.Equals(right);
}
///
/// Determines whether the current CancellationTokenRegistration instance is equal to the
/// specified .
///
/// The other object to which to compare this instance.
/// True, if both this and are equal. False, otherwise.
/// Two CancellationTokenRegistration instances are equal if
/// they both refer to the output of a single call to the same Register method of a
/// CancellationToken .
///
public override bool Equals(object obj)
{
return ((obj is CancellationTokenRegistration) && Equals((CancellationTokenRegistration) obj));
}
///
/// Determines whether the current CancellationToken instance is equal to the
/// specified .
///
/// The other CancellationTokenRegistration to which to compare this instance.
/// True, if both this and are equal. False, otherwise.
/// Two CancellationTokenRegistration instances are equal if
/// they both refer to the output of a single call to the same Register method of a
/// CancellationToken .
///
public bool Equals(CancellationTokenRegistration other)
{
return m_tokenSource == other.m_tokenSource &&
m_callbackInfo == other.m_callbackInfo &&
m_registrationInfo.Source == other.m_registrationInfo.Source &&
m_registrationInfo.Index == other.m_registrationInfo.Index;
}
///
/// Serves as a hash function for a CancellationTokenRegistration. .
///
/// A hash code for the current CancellationTokenRegistration instance.
public override int GetHashCode()
{
if (m_registrationInfo.Source != null)
return m_registrationInfo.Source.GetHashCode() ^ m_registrationInfo.Index.GetHashCode();
return m_registrationInfo.Index.GetHashCode();
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// [....]
////////////////////////////////////////////////////////////////////////////////
using System.Diagnostics.Contracts;
using System.Security.Permissions;
namespace System.Threading
{
///
/// Represents a callback delegate that has been registered with a CancellationToken .
///
///
/// To unregister a callback, dispose the corresponding Registration instance.
///
[HostProtection(Synchronization = true, ExternalThreading = true)]
public struct CancellationTokenRegistration : IEquatable, IDisposable
{
private readonly CancellationTokenSource m_tokenSource;
private readonly CancellationCallbackInfo m_callbackInfo;
private readonly SparselyPopulatedArrayAddInfo m_registrationInfo;
internal CancellationTokenRegistration(
CancellationTokenSource tokenSource,
CancellationCallbackInfo callbackInfo,
SparselyPopulatedArrayAddInfo registrationInfo)
{
m_tokenSource = tokenSource;
m_callbackInfo = callbackInfo;
m_registrationInfo = registrationInfo;
}
///
/// Attempts to deregister the item. If it's already being run, this may fail.
/// Entails a full memory fence.
///
/// True if the callback was found and deregistered, false otherwise.
internal bool TryDeregister()
{
if (m_registrationInfo.Source == null) //can be null for dummy registrations.
return false;
// Try to remove the callback info from the array.
// It is possible the callback info is missing (removed for run, or removed by someone else)
// It is also possible there is info in the array but it doesn't match our current registration's callback info.
CancellationCallbackInfo prevailingCallbackInfoInSlot = m_registrationInfo.Source.SafeAtomicRemove(m_registrationInfo.Index, m_callbackInfo);
if (prevailingCallbackInfoInSlot != m_callbackInfo)
return false; //the callback in the slot wasn't us.
return true;
}
///
/// Disposes of the registration and unregisters the target callback from the associated
/// CancellationToken .
/// If the target callback is currently executing this method will wait until it completes, except
/// in the degenerate cases where a callback method deregisters itself.
///
public void Dispose()
{
// If the token source has been disposed, we must throw.
if (m_tokenSource != null)
m_tokenSource.ThrowIfDisposed();
// Remove the entry from the array.
// This call includes a full memory fence which prevents potential reorderings of the reads below
bool deregisterOccured = TryDeregister();
// We guarantee that we will not return if the callback is being executed (assuming we are not currently called by the callback itself)
// We achieve this by the following rules:
// 1. if we are called in the context of an executing callback, no need to wait (determined by tracking callback-executor threadID)
// - if the currently executing callback is this CTR, then waiting would deadlock. (We choose to return rather than deadlock)
// - if not, then this CTR cannot be the one executing, hence no need to wait
//
// 2. if deregistration failed, and we are on a different thread, then the callback may be running under control of cts.Cancel()
// => poll until cts.ExecutingCallback is not the one we are trying to deregister.
if (m_tokenSource != null &&
m_tokenSource.IsCancellationRequested && //running callbacks has commenced.
! m_tokenSource.IsCancellationCompleted && //running callbacks hasn't finished
!deregisterOccured && //deregistration failed (ie the callback is missing from the list)
m_tokenSource.ThreadIDExecutingCallbacks != Thread.CurrentThread.ManagedThreadId) //the executingThreadID is not this threadID.
{
// Callback execution is in progress, the executing thread is different to us and has taken the callback for execution
// so observe and wait until this target callback is no longer the executing callback.
m_tokenSource.WaitForCallbackToComplete(m_callbackInfo);
}
}
///
/// Determines whether two CancellationTokenRegistration
/// instances are equal.
///
/// The first instance.
/// The second instance.
/// True if the instances are equal; otherwise, false.
public static bool operator ==(CancellationTokenRegistration left, CancellationTokenRegistration right)
{
return left.Equals(right);
}
///
/// Determines whether two CancellationTokenRegistration instances are not equal.
///
/// The first instance.
/// The second instance.
/// True if the instances are not equal; otherwise, false.
public static bool operator !=(CancellationTokenRegistration left, CancellationTokenRegistration right)
{
return !left.Equals(right);
}
///
/// Determines whether the current CancellationTokenRegistration instance is equal to the
/// specified .
///
/// The other object to which to compare this instance.
/// True, if both this and are equal. False, otherwise.
/// Two CancellationTokenRegistration instances are equal if
/// they both refer to the output of a single call to the same Register method of a
/// CancellationToken .
///
public override bool Equals(object obj)
{
return ((obj is CancellationTokenRegistration) && Equals((CancellationTokenRegistration) obj));
}
///
/// Determines whether the current CancellationToken instance is equal to the
/// specified .
///
/// The other CancellationTokenRegistration to which to compare this instance.
/// True, if both this and are equal. False, otherwise.
/// Two CancellationTokenRegistration instances are equal if
/// they both refer to the output of a single call to the same Register method of a
/// CancellationToken .
///
public bool Equals(CancellationTokenRegistration other)
{
return m_tokenSource == other.m_tokenSource &&
m_callbackInfo == other.m_callbackInfo &&
m_registrationInfo.Source == other.m_registrationInfo.Source &&
m_registrationInfo.Index == other.m_registrationInfo.Index;
}
///
/// Serves as a hash function for a CancellationTokenRegistration. .
///
/// A hash code for the current CancellationTokenRegistration instance.
public override int GetHashCode()
{
if (m_registrationInfo.Source != null)
return m_registrationInfo.Source.GetHashCode() ^ m_registrationInfo.Index.GetHashCode();
return m_registrationInfo.Index.GetHashCode();
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TextElementEnumerator.cs
- XmlEncoding.cs
- DataSvcMapFileSerializer.cs
- SecurityTokenProviderContainer.cs
- DrawingGroupDrawingContext.cs
- SortExpressionBuilder.cs
- SmiMetaData.cs
- BooleanProjectedSlot.cs
- HealthMonitoringSection.cs
- CellTreeNode.cs
- EventSourceCreationData.cs
- XmlSchemaImport.cs
- QueryOutputWriter.cs
- DbReferenceCollection.cs
- CompilerScopeManager.cs
- ActivityDesignerHighlighter.cs
- IndexerHelper.cs
- ScrollBarRenderer.cs
- EntityConnection.cs
- MasterPage.cs
- RenderingEventArgs.cs
- MessageFilterTable.cs
- Point3D.cs
- RSAOAEPKeyExchangeDeformatter.cs
- CacheEntry.cs
- FrameworkPropertyMetadata.cs
- HttpModuleAction.cs
- HitTestParameters.cs
- OleStrCAMarshaler.cs
- SequenceNumber.cs
- PageRequestManager.cs
- DefaultValueAttribute.cs
- Enum.cs
- wmiprovider.cs
- EditorPart.cs
- XhtmlBasicTextBoxAdapter.cs
- ResourceIDHelper.cs
- EventWaitHandleSecurity.cs
- Classification.cs
- RowToParametersTransformer.cs
- EntityModelSchemaGenerator.cs
- ADMembershipProvider.cs
- ProgressBar.cs
- ContractListAdapter.cs
- UIAgentAsyncEndRequest.cs
- XPathMessageFilterTable.cs
- HttpWriter.cs
- MediaPlayer.cs
- ReflectionHelper.cs
- MediaTimeline.cs
- InlinedAggregationOperatorEnumerator.cs
- _BufferOffsetSize.cs
- UntrustedRecipientException.cs
- DataBindEngine.cs
- CreateParams.cs
- TouchDevice.cs
- Hex.cs
- UnionCqlBlock.cs
- XmlToDatasetMap.cs
- TableLayoutStyleCollection.cs
- ListSortDescription.cs
- TextEndOfParagraph.cs
- DataGridViewLayoutData.cs
- Stylesheet.cs
- TableLayoutPanel.cs
- UserMapPath.cs
- DataGridState.cs
- AsyncPostBackErrorEventArgs.cs
- SecurityRuntime.cs
- PolicyManager.cs
- DispatcherHooks.cs
- _CookieModule.cs
- ProtectedProviderSettings.cs
- XmlDomTextWriter.cs
- PenContexts.cs
- Expression.cs
- TransformConverter.cs
- QuotedStringFormatReader.cs
- StructuralComparisons.cs
- XslTransformFileEditor.cs
- ObfuscationAttribute.cs
- DataGrid.cs
- TimeSpanSecondsOrInfiniteConverter.cs
- ReliabilityContractAttribute.cs
- DataListCommandEventArgs.cs
- MILUtilities.cs
- LockCookie.cs
- BitmapCodecInfo.cs
- X509DefaultServiceCertificateElement.cs
- AsyncCompletedEventArgs.cs
- JsonEncodingStreamWrapper.cs
- EntityPropertyMappingAttribute.cs
- ClockGroup.cs
- ViewgenContext.cs
- TimerEventSubscription.cs
- Panel.cs
- DbTransaction.cs
- RawAppCommandInputReport.cs
- AsymmetricSignatureFormatter.cs
- CapabilitiesState.cs