Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / Linq / Parallel / Scheduling / QueryTaskGroupState.cs / 1305376 / QueryTaskGroupState.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // // QueryTaskGroupState.cs // //[....] // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Diagnostics.Contracts; namespace System.Linq.Parallel { ////// A collection of tasks used by a single query instance. This type also offers some /// convenient methods for tracing significant ETW events, waiting on tasks, propagating /// exceptions, and performing cancellation activities. /// internal class QueryTaskGroupState { private Task m_rootTask; // The task under which all query tasks root. private int m_alreadyEnded; // Whether the tasks have been waited on already. private CancellationState m_cancellationState; // The cancellation state. private int m_queryId; // Id of this query execution. //------------------------------------------------------------------------------------ // Creates a new shared bit of state among tasks. // internal QueryTaskGroupState(CancellationState cancellationState, int queryId) { m_cancellationState = cancellationState; m_queryId = queryId; } //----------------------------------------------------------------------------------- // Whether this query has ended or not. // internal bool IsAlreadyEnded { get { return m_alreadyEnded == 1; } } //----------------------------------------------------------------------------------- // Cancellation state, used to tear down tasks cooperatively when necessary. // internal CancellationState CancellationState { get { return m_cancellationState; } } //----------------------------------------------------------------------------------- // Id of this query execution. // internal int QueryId { get { return m_queryId; } } //------------------------------------------------------------------------------------ // Marks the beginning of a query's execution. // internal void QueryBegin(Task rootTask) { Contract.Assert(rootTask != null, "Expected a non-null task"); Contract.Assert(m_rootTask == null, "Cannot begin a query more than once"); m_rootTask = rootTask; } //----------------------------------------------------------------------------------- // Marks the end of a query's execution, waiting for all tasks to finish and // propagating any relevant exceptions. Note that the full set of tasks must have // been initialized (with SetTask) before calling this. // internal void QueryEnd(bool userInitiatedDispose) { Contract.Assert(m_rootTask != null); //Contract.Assert(Task.Current == null || (Task.Current != m_rootTask && Task.Current.Parent != m_rootTask)); if (Interlocked.Exchange(ref m_alreadyEnded, 1) == 0) { // There are four cases: // Case #1: Wait produced an exception that is not OCE(ct), or an AggregateException which is not full of OCE(ct) ==> We rethrow. // Case #2: External cancellation has been requested ==> we'll manually throw OCE(externalToken). // Case #3a: We are servicing a call to Dispose() (and possibly also external cancellation has been requested).. simply return. See bug 695173 // Case #3b: The enumerator has already been disposed (and possibly also external cancellation was requested). Throw an ODE. // Case #4: No exceptions or explicit call to Dispose() by this caller ==> we just return. // See also "InlinedAggregationOperator" which duplicates some of this logic for the aggregators. // See also "QueryOpeningEnumerator" which duplicates some of this logic. // See also "ExceptionAggregator" which duplicates some of this logic. try { // Wait for all the tasks to complete // If any of the tasks ended in the Faulted stated, an AggregateException will be thrown. m_rootTask.Wait(); } catch (AggregateException ae) { AggregateException flattenedAE = ae.Flatten(); bool allOCEsOnTrackedExternalCancellationToken = true; for (int i = 0; i < flattenedAE.InnerExceptions.Count; i++) { OperationCanceledException oce = flattenedAE.InnerExceptions[i] as OperationCanceledException; // we only let it pass through iff: // it is not null, not default, and matches the exact token we were given as being the external token // and the external Token is actually canceled (ie not a spoof OCE(extCT) for a non-canceled extCT) if (oce == null || !oce.CancellationToken.IsCancellationRequested || oce.CancellationToken != m_cancellationState.ExternalCancellationToken) { allOCEsOnTrackedExternalCancellationToken = false; break; } } // if all the exceptions were OCE(externalToken), then we will propogate only a single OCE(externalToken) below // otherwise, we flatten the aggregate (because the WaitAll above already aggregated) and rethrow. if (!allOCEsOnTrackedExternalCancellationToken) throw flattenedAE; // Case #1 } finally { m_rootTask.Dispose(); } if (m_cancellationState.MergedCancellationToken.IsCancellationRequested) { // cancellation has occured but no user-delegate exceptions were detected // NOTE: it is important that we see other state variables correctly here, and that // read-reordering hasn't played havoc. // This is OK because // 1. all the state writes (eg in the Initiate* methods) are volatile writes (standard .NET MM) // 2. tokenCancellationRequested is backed by a volatile field, hence the reads below // won't get reordered about the read of token.IsCancellationRequested. // If the query has already been disposed, we don't want to throw an OCE (this is a fix for bug 695173.) if (!m_cancellationState.TopLevelDisposedFlag.Value) { CancellationState.ThrowWithStandardMessageIfCanceled(m_cancellationState.ExternalCancellationToken); // Case #2 } //otherwise, given that there were no user-delegate exceptions (they would have been rethrown above), //the only remaining situation is user-initiated dispose. Contract.Assert(m_cancellationState.TopLevelDisposedFlag.Value); // If we aren't actively disposing, that means somebody else previously disposed // of the enumerator. We must throw an ObjectDisposedException. if (!userInitiatedDispose) { throw new ObjectDisposedException("enumerator", SR.GetString(SR.PLINQ_DisposeRequested)); // Case #3 } } // Case #4. nothing to do. } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // // QueryTaskGroupState.cs // //[....] // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Diagnostics.Contracts; namespace System.Linq.Parallel { ////// A collection of tasks used by a single query instance. This type also offers some /// convenient methods for tracing significant ETW events, waiting on tasks, propagating /// exceptions, and performing cancellation activities. /// internal class QueryTaskGroupState { private Task m_rootTask; // The task under which all query tasks root. private int m_alreadyEnded; // Whether the tasks have been waited on already. private CancellationState m_cancellationState; // The cancellation state. private int m_queryId; // Id of this query execution. //------------------------------------------------------------------------------------ // Creates a new shared bit of state among tasks. // internal QueryTaskGroupState(CancellationState cancellationState, int queryId) { m_cancellationState = cancellationState; m_queryId = queryId; } //----------------------------------------------------------------------------------- // Whether this query has ended or not. // internal bool IsAlreadyEnded { get { return m_alreadyEnded == 1; } } //----------------------------------------------------------------------------------- // Cancellation state, used to tear down tasks cooperatively when necessary. // internal CancellationState CancellationState { get { return m_cancellationState; } } //----------------------------------------------------------------------------------- // Id of this query execution. // internal int QueryId { get { return m_queryId; } } //------------------------------------------------------------------------------------ // Marks the beginning of a query's execution. // internal void QueryBegin(Task rootTask) { Contract.Assert(rootTask != null, "Expected a non-null task"); Contract.Assert(m_rootTask == null, "Cannot begin a query more than once"); m_rootTask = rootTask; } //----------------------------------------------------------------------------------- // Marks the end of a query's execution, waiting for all tasks to finish and // propagating any relevant exceptions. Note that the full set of tasks must have // been initialized (with SetTask) before calling this. // internal void QueryEnd(bool userInitiatedDispose) { Contract.Assert(m_rootTask != null); //Contract.Assert(Task.Current == null || (Task.Current != m_rootTask && Task.Current.Parent != m_rootTask)); if (Interlocked.Exchange(ref m_alreadyEnded, 1) == 0) { // There are four cases: // Case #1: Wait produced an exception that is not OCE(ct), or an AggregateException which is not full of OCE(ct) ==> We rethrow. // Case #2: External cancellation has been requested ==> we'll manually throw OCE(externalToken). // Case #3a: We are servicing a call to Dispose() (and possibly also external cancellation has been requested).. simply return. See bug 695173 // Case #3b: The enumerator has already been disposed (and possibly also external cancellation was requested). Throw an ODE. // Case #4: No exceptions or explicit call to Dispose() by this caller ==> we just return. // See also "InlinedAggregationOperator" which duplicates some of this logic for the aggregators. // See also "QueryOpeningEnumerator" which duplicates some of this logic. // See also "ExceptionAggregator" which duplicates some of this logic. try { // Wait for all the tasks to complete // If any of the tasks ended in the Faulted stated, an AggregateException will be thrown. m_rootTask.Wait(); } catch (AggregateException ae) { AggregateException flattenedAE = ae.Flatten(); bool allOCEsOnTrackedExternalCancellationToken = true; for (int i = 0; i < flattenedAE.InnerExceptions.Count; i++) { OperationCanceledException oce = flattenedAE.InnerExceptions[i] as OperationCanceledException; // we only let it pass through iff: // it is not null, not default, and matches the exact token we were given as being the external token // and the external Token is actually canceled (ie not a spoof OCE(extCT) for a non-canceled extCT) if (oce == null || !oce.CancellationToken.IsCancellationRequested || oce.CancellationToken != m_cancellationState.ExternalCancellationToken) { allOCEsOnTrackedExternalCancellationToken = false; break; } } // if all the exceptions were OCE(externalToken), then we will propogate only a single OCE(externalToken) below // otherwise, we flatten the aggregate (because the WaitAll above already aggregated) and rethrow. if (!allOCEsOnTrackedExternalCancellationToken) throw flattenedAE; // Case #1 } finally { m_rootTask.Dispose(); } if (m_cancellationState.MergedCancellationToken.IsCancellationRequested) { // cancellation has occured but no user-delegate exceptions were detected // NOTE: it is important that we see other state variables correctly here, and that // read-reordering hasn't played havoc. // This is OK because // 1. all the state writes (eg in the Initiate* methods) are volatile writes (standard .NET MM) // 2. tokenCancellationRequested is backed by a volatile field, hence the reads below // won't get reordered about the read of token.IsCancellationRequested. // If the query has already been disposed, we don't want to throw an OCE (this is a fix for bug 695173.) if (!m_cancellationState.TopLevelDisposedFlag.Value) { CancellationState.ThrowWithStandardMessageIfCanceled(m_cancellationState.ExternalCancellationToken); // Case #2 } //otherwise, given that there were no user-delegate exceptions (they would have been rethrown above), //the only remaining situation is user-initiated dispose. Contract.Assert(m_cancellationState.TopLevelDisposedFlag.Value); // If we aren't actively disposing, that means somebody else previously disposed // of the enumerator. We must throw an ObjectDisposedException. if (!userInitiatedDispose) { throw new ObjectDisposedException("enumerator", SR.GetString(SR.PLINQ_DisposeRequested)); // Case #3 } } // Case #4. nothing to do. } } } } // 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
- DBSqlParser.cs
- TTSVoice.cs
- ValidationUtility.cs
- BooleanFunctions.cs
- SHA1CryptoServiceProvider.cs
- ClientApiGenerator.cs
- ConfigurationErrorsException.cs
- SystemGatewayIPAddressInformation.cs
- EntityClientCacheEntry.cs
- DateTimeSerializationSection.cs
- ControlBuilderAttribute.cs
- SqlRetyper.cs
- GroupDescription.cs
- DataTableMappingCollection.cs
- XmlQueryRuntime.cs
- PngBitmapEncoder.cs
- BamlLocalizer.cs
- TypeUsageBuilder.cs
- ProcessThreadDesigner.cs
- exports.cs
- RenamedEventArgs.cs
- DataColumnChangeEvent.cs
- AQNBuilder.cs
- XmlILOptimizerVisitor.cs
- LoadedEvent.cs
- ZipIOExtraFieldElement.cs
- FileNotFoundException.cs
- Label.cs
- Documentation.cs
- TextParentUndoUnit.cs
- x509store.cs
- ZipFileInfo.cs
- WriteableBitmap.cs
- Listener.cs
- WindowsContainer.cs
- CodeNamespaceCollection.cs
- NotImplementedException.cs
- ObjectRef.cs
- TraceUtils.cs
- Clause.cs
- XmlSchemaAttributeGroup.cs
- SegmentInfo.cs
- JavaScriptString.cs
- LeaseManager.cs
- EntityDataSourceColumn.cs
- XmlDataLoader.cs
- DebugView.cs
- DrawingCollection.cs
- XmlSchemaCompilationSettings.cs
- AtomEntry.cs
- XPathNodeIterator.cs
- HtmlFormParameterWriter.cs
- DataTableReader.cs
- RectangleGeometry.cs
- CompilerError.cs
- SafeProcessHandle.cs
- SBCSCodePageEncoding.cs
- XmlSerializerNamespaces.cs
- TagMapInfo.cs
- FormDocumentDesigner.cs
- WebServiceParameterData.cs
- CompoundFileIOPermission.cs
- ProxyWebPartConnectionCollection.cs
- CookieHandler.cs
- QueryContinueDragEvent.cs
- BehaviorEditorPart.cs
- followingsibling.cs
- StatusBar.cs
- HtmlTableRow.cs
- EDesignUtil.cs
- ApplicationManager.cs
- InputDevice.cs
- ServiceBuildProvider.cs
- BitmapPalettes.cs
- UInt32.cs
- XmlUtil.cs
- LinqDataSourceValidationException.cs
- PassportAuthenticationEventArgs.cs
- ShapingEngine.cs
- MappingException.cs
- CompatibleIComparer.cs
- ServiceModelStringsVersion1.cs
- MonthChangedEventArgs.cs
- SizeIndependentAnimationStorage.cs
- bidPrivateBase.cs
- IndexedGlyphRun.cs
- ConfigurationLockCollection.cs
- MenuStrip.cs
- DNS.cs
- ResourcesChangeInfo.cs
- ColumnMapCopier.cs
- ResXResourceWriter.cs
- EdmRelationshipRoleAttribute.cs
- IgnoreFileBuildProvider.cs
- StoreAnnotationsMap.cs
- _NegoState.cs
- CompensatableSequenceActivity.cs
- PasswordTextContainer.cs
- ApplicationException.cs
- ExtensibleClassFactory.cs