Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Core / System / Linq / Parallel / Scheduling / CancellationState.cs
blobe84bced8117e78d848e8a1c4ea24ba3cd59f4d3a
1 // ==++==
2 //
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 //
5 // ==--==
6 // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
7 //
8 // CancellationState.cs
9 //
10 // <OWNER>Microsoft</OWNER>
12 // A bag of cancellation-related items that are passed around as a group.
14 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
16 using System;
17 using System.Collections.Generic;
18 using System.Threading;
19 #if SILVERLIGHT
20 using System.Core; // for System.Core.SR
21 #endif
23 namespace System.Linq.Parallel
25 internal class CancellationState
27 // a cancellation signal that can be set internally to prompt early query termination.
28 internal CancellationTokenSource InternalCancellationTokenSource;
30 // the external cancellationToken that the user sets to ask for the query to terminate early.
31 // this has to be tracked explicitly so that an OCE(externalToken) can be thrown as the query
32 // execution unravels.
33 internal CancellationToken ExternalCancellationToken;
35 // A combined token Source for internal/external cancellation, defining the total cancellation state.
36 internal CancellationTokenSource MergedCancellationTokenSource;
38 // A combined token for internal/external cancellation, defining the total cancellation state.
39 internal CancellationToken MergedCancellationToken
41 get
43 if( MergedCancellationTokenSource != null)
44 return MergedCancellationTokenSource.Token;
45 else
46 return new CancellationToken(false);
50 // A shared boolean flag to track whether a query-opening-enumerator dispose has occured.
51 internal Shared<bool> TopLevelDisposedFlag;
53 internal CancellationState(CancellationToken externalCancellationToken)
55 ExternalCancellationToken = externalCancellationToken;
56 TopLevelDisposedFlag = new Shared<bool>(false); //it would always be initialised to false, so no harm doing it here and avoid #if around constructors.
59 /// <summary>
60 /// Poll frequency (number of loops per cancellation check) for situations where per-1-loop testing is too high an overhead.
61 /// </summary>
62 internal const int POLL_INTERVAL = 63; //must be of the form (2^n)-1.
64 // The two main situations requiring POLL_INTERVAL are:
65 // 1. inner loops of sorting/merging operations
66 // 2. tight loops that perform very little work per MoveNext call.
67 // Testing has shown both situations have similar requirements and can share the same constant for polling interval.
68 //
69 // Because the poll checks are per-N loops, if there are delays in user code, they may affect cancellation timeliness.
70 // Guidance is that all user-delegates should perform cancellation checks at least every 1ms.
71 //
72 // Inner loop code should poll once per n loop, typically via:
73 // if ((i++ & CancellationState.POLL_INTERVAL) == 0)
74 // CancellationState.ThrowIfCanceled(m_cancellationToken);
75 // (Note, this only behaves as expected if FREQ is of the form (2^n)-1
77 /// <summary>
78 /// Throws an OCE if the merged token has been canceled.
79 /// </summary>
80 /// <param name="token">A token to check for cancelation.</param>
81 internal static void ThrowIfCanceled(CancellationToken token)
83 if (token.IsCancellationRequested)
84 throw new OperationCanceledException(token);
87 // Test if external cancellation was requested and occured, and if so throw a standardize OCE with standardized message
88 internal static void ThrowWithStandardMessageIfCanceled(CancellationToken externalCancellationToken)
90 if (externalCancellationToken.IsCancellationRequested)
92 string oceMessage = SR.GetString(SR.PLINQ_ExternalCancellationRequested);
93 throw new OperationCanceledException(oceMessage, externalCancellationToken);