diff options
author | stephentoub <stoub@microsoft.com> | 2016-01-27 10:41:27 -0800 |
---|---|---|
committer | stephentoub <stoub@microsoft.com> | 2016-01-27 10:41:27 -0800 |
commit | 42dfe9b8373b7c72c4a314a9166a8da4e433b979 (patch) | |
tree | b86244ffce7e4765bab772f7eb806963c60ef4b1 /src/mscorlib | |
parent | 06bcf2a997da3127847d8c05e151d582f757b7d4 (diff) | |
download | coreclr-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.cs | 32 |
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; } |