summaryrefslogtreecommitdiff
path: root/src/mscorlib
diff options
context:
space:
mode:
authorstephentoub <stoub@microsoft.com>2016-01-27 10:41:27 -0800
committerstephentoub <stoub@microsoft.com>2016-01-27 10:41:27 -0800
commit42dfe9b8373b7c72c4a314a9166a8da4e433b979 (patch)
treeb86244ffce7e4765bab772f7eb806963c60ef4b1 /src/mscorlib
parent06bcf2a997da3127847d8c05e151d582f757b7d4 (diff)
downloadcoreclr-42dfe9b8373b7c72c4a314a9166a8da4e433b979.tar.gz
coreclr-42dfe9b8373b7c72c4a314a9166a8da4e433b979.tar.bz2
coreclr-42dfe9b8373b7c72c4a314a9166a8da4e433b979.zip
Reduce size of CancellationCallbackInfo
Each registration with a cancelable CancellationToken results in allocating a CancellationCallbackInfo instance to store the relevant state, e.g. the action to invoke, the associated CTS, etc. CancellationToken.Register has a little-known and very-little-used feature that enables the callback to be automatically sent to a captured SynchronizationContext, and as such the CancellationCallbackInfo has a field to store the SynchronizationContext, too. But this field is almost always null. This change reduces the size of CancellationCallbackInfo from 56 to 48 bytes on 64-bit by moving the TargetSynchronizationContext field to a derived type. The derived instance with the extra field is only allocated when there is a SynchronizationContext captured.
Diffstat (limited to 'src/mscorlib')
-rw-r--r--src/mscorlib/src/System/Threading/CancellationTokenSource.cs32
1 files changed, 24 insertions, 8 deletions
diff --git a/src/mscorlib/src/System/Threading/CancellationTokenSource.cs b/src/mscorlib/src/System/Threading/CancellationTokenSource.cs
index 7e30538836..1e38135df8 100644
--- a/src/mscorlib/src/System/Threading/CancellationTokenSource.cs
+++ b/src/mscorlib/src/System/Threading/CancellationTokenSource.cs
@@ -638,7 +638,9 @@ namespace System.Threading
int myIndex = Thread.CurrentThread.ManagedThreadId % s_nLists;
- CancellationCallbackInfo callbackInfo = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);
+ CancellationCallbackInfo callbackInfo = targetSyncContext != null ?
+ new CancellationCallbackInfo.WithSyncContext(callback, stateForCallback, executionContext, this, targetSyncContext) :
+ new CancellationCallbackInfo(callback, stateForCallback, executionContext, this);
//allocate the callback list array
var registeredCallbacksLists = m_registeredCallbacksLists;
@@ -769,10 +771,11 @@ namespace System.Threading
// We assume that syncCtx.Send() has forwarded on user exceptions when appropriate.
try
{
- if (m_executingCallback.TargetSyncContext != null)
+ var wsc = m_executingCallback as CancellationCallbackInfo.WithSyncContext;
+ if (wsc != null)
{
-
- m_executingCallback.TargetSyncContext.Send(CancellationCallbackCoreWork_OnSyncContext, args);
+ Contract.Assert(wsc.TargetSyncContext != null, "Should only have derived CCI if non-null SyncCtx");
+ wsc.TargetSyncContext.Send(CancellationCallbackCoreWork_OnSyncContext, args);
// CancellationCallbackCoreWork_OnSyncContext may have altered ThreadIDExecutingCallbacks, so reset it.
ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
}
@@ -979,17 +982,30 @@ namespace System.Threading
{
internal readonly Action<object> Callback;
internal readonly object StateForCallback;
- internal readonly SynchronizationContext TargetSyncContext;
internal readonly ExecutionContext TargetExecutionContext;
internal readonly CancellationTokenSource CancellationTokenSource;
+ internal sealed class WithSyncContext : CancellationCallbackInfo
+ {
+ // Very rarely used, and as such it is separated out into a
+ // a derived type so that the space for it is pay-for-play.
+ internal readonly SynchronizationContext TargetSyncContext;
+
+ internal WithSyncContext(
+ Action<object> callback, object stateForCallback, ExecutionContext targetExecutionContext, CancellationTokenSource cancellationTokenSource,
+ SynchronizationContext targetSyncContext) :
+ base(callback, stateForCallback, targetExecutionContext, cancellationTokenSource)
+ {
+ TargetSyncContext = targetSyncContext;
+ }
+
+ }
+
internal CancellationCallbackInfo(
- Action<object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext targetExecutionContext,
- CancellationTokenSource cancellationTokenSource)
+ Action<object> callback, object stateForCallback, ExecutionContext targetExecutionContext, CancellationTokenSource cancellationTokenSource)
{
Callback = callback;
StateForCallback = stateForCallback;
- TargetSyncContext = targetSyncContext;
TargetExecutionContext = targetExecutionContext;
CancellationTokenSource = cancellationTokenSource;
}