diff --git a/Package/Core/Linq/CompilerServices/AsyncStreamYielder.cs b/Package/Core/Linq/CompilerServices/AsyncStreamYielder.cs index cc7951bb..a3c22ec3 100644 --- a/Package/Core/Linq/CompilerServices/AsyncStreamYielder.cs +++ b/Package/Core/Linq/CompilerServices/AsyncStreamYielder.cs @@ -13,7 +13,7 @@ namespace Proto.Promises.CompilerServices #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] #endif - public readonly partial struct AsyncStreamYielder : ICriticalNotifyCompletion, Internal.IPromiseAwaiter + public readonly partial struct AsyncStreamYielder : ICriticalNotifyCompletion, Internal.IPromiseAwareAwaiter { private readonly Internal.PromiseRefBase.AsyncEnumerableWithIterator _target; private readonly int _enumerableId; @@ -62,7 +62,7 @@ public void GetResult() => _target.GetResultForAsyncStreamYielder(_enumerableId); [MethodImpl(Internal.InlineOption)] - void Internal.IPromiseAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) + void Internal.IPromiseAwareAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) => _target.AwaitOnCompletedForAsyncStreamYielder(asyncPromiseRef, _enumerableId); void INotifyCompletion.OnCompleted(Action continuation) diff --git a/Package/Core/Linq/Internal/AsyncEnumerableInternal.cs b/Package/Core/Linq/Internal/AsyncEnumerableInternal.cs index b4993833..5858da90 100644 --- a/Package/Core/Linq/Internal/AsyncEnumerableInternal.cs +++ b/Package/Core/Linq/Internal/AsyncEnumerableInternal.cs @@ -280,12 +280,12 @@ internal override sealed void Handle(PromiseRefBase handler, Promise.State state if (Interlocked.CompareExchange(ref _enumerableId, _iteratorCompleteId, _iteratorCompleteExpectedId) != _iteratorCompleteExpectedId) { handler.MaybeReportUnhandledAndDispose(state); - _rejectContainer = CreateRejectContainer(new InvalidOperationException("AsyncEnumerable.Create async iterator completed invalidly. Did you YieldAsync without await?"), int.MinValue, null, this); + RejectContainer = CreateRejectContainer(new InvalidOperationException("AsyncEnumerable.Create async iterator completed invalidly. Did you YieldAsync without await?"), int.MinValue, null, this); state = Promise.State.Rejected; } else { - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.MaybeDispose(); } @@ -298,7 +298,7 @@ protected void HandleFromSynchronouslyCompletedIterator() Promise.State state = Promise.State.Resolved; if (Interlocked.CompareExchange(ref _enumerableId, _iteratorCompleteId, _iteratorCompleteExpectedId) != _iteratorCompleteExpectedId) { - _rejectContainer = CreateRejectContainer(new InvalidOperationException("AsyncEnumerable.Create async iterator completed invalidly. Did you YieldAsync without await?"), int.MinValue, null, this); + RejectContainer = CreateRejectContainer(new InvalidOperationException("AsyncEnumerable.Create async iterator completed invalidly. Did you YieldAsync without await?"), int.MinValue, null, this); state = Promise.State.Rejected; } HandleNextInternal(state); diff --git a/Package/Core/Linq/Internal/AsyncStreamAwaiterForLinqExtensionInternal.cs b/Package/Core/Linq/Internal/AsyncStreamAwaiterForLinqExtensionInternal.cs index e5c6cdc1..be96ac48 100644 --- a/Package/Core/Linq/Internal/AsyncStreamAwaiterForLinqExtensionInternal.cs +++ b/Package/Core/Linq/Internal/AsyncStreamAwaiterForLinqExtensionInternal.cs @@ -17,7 +17,7 @@ partial class PromiseRefBase #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] #endif - internal readonly partial struct AsyncStreamAwaiterForLinqExtension : ICriticalNotifyCompletion, IPromiseAwaiter + internal readonly partial struct AsyncStreamAwaiterForLinqExtension : ICriticalNotifyCompletion, IPromiseAwareAwaiter { private readonly AsyncEnumerableWithIterator _target; private readonly int _enumerableId; @@ -63,7 +63,7 @@ public void GetResult() } [MethodImpl(InlineOption)] - void IPromiseAwaiter.AwaitOnCompletedInternal(PromiseRefBase asyncPromiseRef) + void IPromiseAwareAwaiter.AwaitOnCompletedInternal(PromiseRefBase asyncPromiseRef) => _target.AwaitOnCompletedForAsyncStreamYielder(asyncPromiseRef, _enumerableId, hasValue: false); void INotifyCompletion.OnCompleted(Action continuation) => throw new System.InvalidOperationException("Must only be used in async Linq extension methods."); diff --git a/Package/Core/Linq/Internal/MergeInternal.cs b/Package/Core/Linq/Internal/MergeInternal.cs index 13857eaf..052896f4 100644 --- a/Package/Core/Linq/Internal/MergeInternal.cs +++ b/Package/Core/Linq/Internal/MergeInternal.cs @@ -85,7 +85,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state, int i // The async enumerator was canceled or rejected, notify all enumerators that they don't need to continue executing. CancelEnumerators(); } - _enumeratorsAndRejectContainers[index].rejectContainer = handler._rejectContainer; + _enumeratorsAndRejectContainers[index].rejectContainer = handler.RejectContainer; _readyQueue.RemoveProducer(); } } diff --git a/Package/Core/PromiseGroups/Internal/PromiseAllGroupInternal.cs b/Package/Core/PromiseGroups/Internal/PromiseAllGroupInternal.cs index 42c51ab0..dbe43bf8 100644 --- a/Package/Core/PromiseGroups/Internal/PromiseAllGroupInternal.cs +++ b/Package/Core/PromiseGroups/Internal/PromiseAllGroupInternal.cs @@ -73,7 +73,7 @@ private Promise.State CompleteAndGetState() _result[passthrough.Index] = owner.GetResult(); if (owner.State == Promise.State.Rejected) { - RecordException(owner._rejectContainer.GetValueAsException()); + RecordException(owner.RejectContainer.GetValueAsException()); } passthrough.Dispose(); } @@ -81,7 +81,7 @@ private Promise.State CompleteAndGetState() if (_exceptions != null) { state = Promise.State.Rejected; - _rejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); + RejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); _exceptions = null; } diff --git a/Package/Core/PromiseGroups/Internal/PromiseAllResultsGroupInternal.cs b/Package/Core/PromiseGroups/Internal/PromiseAllResultsGroupInternal.cs index 7b80bd02..673d11a1 100644 --- a/Package/Core/PromiseGroups/Internal/PromiseAllResultsGroupInternal.cs +++ b/Package/Core/PromiseGroups/Internal/PromiseAllResultsGroupInternal.cs @@ -70,7 +70,7 @@ private Promise.State CompleteAndGetState() if (_exceptions != null) { state = Promise.State.Rejected; - _rejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); + RejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); _exceptions = null; } @@ -79,7 +79,7 @@ private Promise.State CompleteAndGetState() { var passthrough = passthroughs.Pop(); var owner = passthrough.Owner; - _result[passthrough.Index] = new Promise.ResultContainer(owner._rejectContainer, owner.State); + _result[passthrough.Index] = new Promise.ResultContainer(owner.RejectContainer, owner.State); passthrough.Dispose(); } @@ -153,7 +153,7 @@ private Promise.State CompleteAndGetState() if (_exceptions != null) { state = Promise.State.Rejected; - _rejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); + RejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); _exceptions = null; } @@ -162,7 +162,7 @@ private Promise.State CompleteAndGetState() { var passthrough = passthroughs.Pop(); var owner = passthrough.Owner; - _result[passthrough.Index] = new Promise.ResultContainer(owner.GetResult(), owner._rejectContainer, owner.State); + _result[passthrough.Index] = new Promise.ResultContainer(owner.GetResult(), owner.RejectContainer, owner.State); passthrough.Dispose(); } diff --git a/Package/Core/PromiseGroups/Internal/PromiseEachGroupInternal.cs b/Package/Core/PromiseGroups/Internal/PromiseEachGroupInternal.cs index 69d15c52..ab99f14a 100644 --- a/Package/Core/PromiseGroups/Internal/PromiseEachGroupInternal.cs +++ b/Package/Core/PromiseGroups/Internal/PromiseEachGroupInternal.cs @@ -272,7 +272,7 @@ private void MaybeHandleDisposeAsync() return; } - _rejectContainer = CreateRejectContainer(exception, int.MinValue, null, this); + RejectContainer = CreateRejectContainer(exception, int.MinValue, null, this); HandleNextInternal(Promise.State.Rejected); } diff --git a/Package/Core/PromiseGroups/Internal/PromiseMergeGroupInternal.cs b/Package/Core/PromiseGroups/Internal/PromiseMergeGroupInternal.cs index 179d4bc6..9d0ebed2 100644 --- a/Package/Core/PromiseGroups/Internal/PromiseMergeGroupInternal.cs +++ b/Package/Core/PromiseGroups/Internal/PromiseMergeGroupInternal.cs @@ -129,7 +129,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) CancelGroup(); if (state == Promise.State.Rejected) { - RecordException(handler._rejectContainer.GetValueAsException()); + RecordException(handler.RejectContainer.GetValueAsException()); } } handler.MaybeDispose(); @@ -147,7 +147,7 @@ private Promise.State CompleteAndGetState() return _completeState; } - _rejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); + RejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); _exceptions = null; return Promise.State.Rejected; } @@ -231,7 +231,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) s_getResult.Invoke(owner, index, ref _result); if (owner.State == Promise.State.Rejected) { - var exception = owner._rejectContainer.GetValueAsException(); + var exception = owner.RejectContainer.GetValueAsException(); if (_isExtended & index == 0) { // If this is an extended merge group, we need to extract the inner exceptions of the first cluster to make a flattened AggregateException. @@ -253,13 +253,13 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) if (group._exceptions != null) { state = Promise.State.Rejected; - _rejectContainer = CreateRejectContainer(new AggregateException(group._exceptions), int.MinValue, null, this); + RejectContainer = CreateRejectContainer(new AggregateException(group._exceptions), int.MinValue, null, this); group._exceptions = null; } else { // The group may have been completed by a void promise, in which case it already converted its exceptions to a reject container. - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; } group.MaybeDispose(); diff --git a/Package/Core/PromiseGroups/Internal/PromiseMergeResultsGroupInternal.cs b/Package/Core/PromiseGroups/Internal/PromiseMergeResultsGroupInternal.cs index 43d820d8..0e543ea2 100644 --- a/Package/Core/PromiseGroups/Internal/PromiseMergeResultsGroupInternal.cs +++ b/Package/Core/PromiseGroups/Internal/PromiseMergeResultsGroupInternal.cs @@ -66,7 +66,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) { // If this is an extended merge group, we need to propagate the exceptions from cancelation token callbacks. state = Promise.State.Rejected; - _rejectContainer = owner._rejectContainer; + RejectContainer = owner.RejectContainer; } passthrough.Dispose(); } @@ -75,14 +75,14 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) { // In case any cancelation token callbacks threw, we propagate them out of this promise instead of resolving this and ignoring the exceptions. state = Promise.State.Rejected; - _rejectContainer = CreateRejectContainer(new AggregateException(group._exceptions), int.MinValue, null, this); + RejectContainer = CreateRejectContainer(new AggregateException(group._exceptions), int.MinValue, null, this); group._exceptions = null; } - else if (handler._rejectContainer != null) + else if (handler.RejectContainer != null) { // The group may have been already completed, in which case it already converted its exceptions to a reject container. state = Promise.State.Rejected; - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; } group.MaybeDispose(); diff --git a/Package/Core/PromiseGroups/Internal/PromiseRaceGroupInternal.cs b/Package/Core/PromiseGroups/Internal/PromiseRaceGroupInternal.cs index be2be13e..eb3ba9b8 100644 --- a/Package/Core/PromiseGroups/Internal/PromiseRaceGroupInternal.cs +++ b/Package/Core/PromiseGroups/Internal/PromiseRaceGroupInternal.cs @@ -33,7 +33,7 @@ private Promise.State CompleteAndGetState() if ((state != Promise.State.Resolved | _cancelationThrew) & _exceptions != null) { state = Promise.State.Rejected; - _rejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); + RejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); } _exceptions = null; return state; @@ -143,7 +143,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) { if (state == Promise.State.Rejected) { - RecordException(handler._rejectContainer.GetValueAsException()); + RecordException(handler.RejectContainer.GetValueAsException()); } if (_cancelOnNonResolved) { @@ -203,7 +203,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state, int i { if (state == Promise.State.Rejected) { - RecordException(handler._rejectContainer.GetValueAsException()); + RecordException(handler.RejectContainer.GetValueAsException()); } if (_cancelOnNonResolved) { @@ -263,7 +263,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state, int i { if (state == Promise.State.Rejected) { - RecordException(handler._rejectContainer.GetValueAsException()); + RecordException(handler.RejectContainer.GetValueAsException()); } if (_cancelOnNonResolved) { diff --git a/Package/Core/PromiseGroups/PromiseMergeResultsGroup.cs b/Package/Core/PromiseGroups/PromiseMergeResultsGroup.cs index b048e537..8beaeeb9 100644 --- a/Package/Core/PromiseGroups/PromiseMergeResultsGroup.cs +++ b/Package/Core/PromiseGroups/PromiseMergeResultsGroup.cs @@ -1359,7 +1359,7 @@ private static class MergeResult [MethodImpl(Internal.InlineOption)] private static void GetMergeResult(Internal.PromiseRefBase handler, int index, ref Promise.ResultContainer result) { - result = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); } #if NETCOREAPP || UNITY_2021_2_OR_NEWER @@ -1385,7 +1385,7 @@ private static class MergeResultVoid [MethodImpl(Internal.InlineOption)] private static void GetMergeResult(Internal.PromiseRefBase handler, int index, ref ResultContainer result) { - result = new ResultContainer(handler._rejectContainer, handler.State); + result = new ResultContainer(handler.RejectContainer, handler.State); } #if NETCOREAPP || UNITY_2021_2_OR_NEWER diff --git a/Package/Core/Promises/CompilerServices/ConfiguredPromiseAwaiters.cs b/Package/Core/Promises/CompilerServices/ConfiguredPromiseAwaiters.cs index 367bf161..f3445890 100644 --- a/Package/Core/Promises/CompilerServices/ConfiguredPromiseAwaiters.cs +++ b/Package/Core/Promises/CompilerServices/ConfiguredPromiseAwaiters.cs @@ -67,7 +67,7 @@ static ConfiguredPromiseNoThrowAwaiter() #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] #endif - public readonly partial struct ConfiguredPromiseAwaiterVoid : ICriticalNotifyCompletion, Internal.IPromiseAwaiter + public readonly partial struct ConfiguredPromiseAwaiterVoid : ICriticalNotifyCompletion, Internal.IPromiseAwareAwaiter { private readonly Promise _promise; private readonly ContinuationOptions _continuationOptions; @@ -155,14 +155,14 @@ public void UnsafeOnCompleted(Action continuation) => OnCompleted(continuation); [MethodImpl(Internal.InlineOption)] - void Internal.IPromiseAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) + void Internal.IPromiseAwareAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) { if (_continuationOptions.IsSynchronous) { asyncPromiseRef.HookupAwaiter(_promise._ref, _promise._id); return; } - Internal.PromiseRefBase.ConfiguredAsyncPromiseContinuer.ConfigureAsyncContinuation(asyncPromiseRef, _continuationOptions.GetContinuationContext(), _promise._ref, _promise._id); + asyncPromiseRef.HookupAwaiterWithContext(_promise._ref, _promise._id, _continuationOptions.GetContinuationContext()); } static partial void ValidateArgument(TArg arg, string argName, int skipFrames); @@ -179,7 +179,7 @@ static partial void ValidateArgument(TArg arg, string argName, int skipFra #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] #endif - public readonly partial struct ConfiguredPromiseAwaiter : ICriticalNotifyCompletion, Internal.IPromiseAwaiter + public readonly partial struct ConfiguredPromiseAwaiter : ICriticalNotifyCompletion, Internal.IPromiseAwareAwaiter { private readonly Promise _promise; private readonly ContinuationOptions _continuationOptions; @@ -268,14 +268,14 @@ public void UnsafeOnCompleted(Action continuation) => OnCompleted(continuation); [MethodImpl(Internal.InlineOption)] - void Internal.IPromiseAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) + void Internal.IPromiseAwareAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) { if (_continuationOptions.IsSynchronous) { asyncPromiseRef.HookupAwaiter(_promise._ref, _promise._id); return; } - Internal.PromiseRefBase.ConfiguredAsyncPromiseContinuer.ConfigureAsyncContinuation(asyncPromiseRef, _continuationOptions.GetContinuationContext(), _promise._ref, _promise._id); + asyncPromiseRef.HookupAwaiterWithContext(_promise._ref, _promise._id, _continuationOptions.GetContinuationContext()); } static partial void ValidateArgument(TArg arg, string argName, int skipFrames); @@ -292,7 +292,7 @@ static partial void ValidateArgument(TArg arg, string argName, int skipFra #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] #endif - public readonly partial struct ConfiguredPromiseNoThrowAwaiterVoid : ICriticalNotifyCompletion, Internal.IPromiseAwaiter + public readonly partial struct ConfiguredPromiseNoThrowAwaiterVoid : ICriticalNotifyCompletion, Internal.IPromiseAwareAwaiter { private readonly Promise _promise; private readonly ContinuationOptions _continuationOptions; @@ -373,14 +373,14 @@ public void UnsafeOnCompleted(Action continuation) => OnCompleted(continuation); [MethodImpl(Internal.InlineOption)] - void Internal.IPromiseAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) + void Internal.IPromiseAwareAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) { if (_continuationOptions.IsSynchronous) { asyncPromiseRef.HookupAwaiter(_promise._ref, _promise._id); return; } - Internal.PromiseRefBase.ConfiguredAsyncPromiseContinuer.ConfigureAsyncContinuation(asyncPromiseRef, _continuationOptions.GetContinuationContext(), _promise._ref, _promise._id); + asyncPromiseRef.HookupAwaiterWithContext(_promise._ref, _promise._id, _continuationOptions.GetContinuationContext()); } static partial void ValidateArgument(TArg arg, string argName, int skipFrames); @@ -397,7 +397,7 @@ static partial void ValidateArgument(TArg arg, string argName, int skipFra #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] #endif - public readonly partial struct ConfiguredPromiseNoThrowAwaiter : ICriticalNotifyCompletion, Internal.IPromiseAwaiter + public readonly partial struct ConfiguredPromiseNoThrowAwaiter : ICriticalNotifyCompletion, Internal.IPromiseAwareAwaiter { private readonly Promise _promise; private readonly ContinuationOptions _continuationOptions; @@ -478,14 +478,14 @@ public void UnsafeOnCompleted(Action continuation) => OnCompleted(continuation); [MethodImpl(Internal.InlineOption)] - void Internal.IPromiseAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) + void Internal.IPromiseAwareAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) { if (_continuationOptions.IsSynchronous) { asyncPromiseRef.HookupAwaiter(_promise._ref, _promise._id); return; } - Internal.PromiseRefBase.ConfiguredAsyncPromiseContinuer.ConfigureAsyncContinuation(asyncPromiseRef, _continuationOptions.GetContinuationContext(), _promise._ref, _promise._id); + asyncPromiseRef.HookupAwaiterWithContext(_promise._ref, _promise._id, _continuationOptions.GetContinuationContext()); } static partial void ValidateArgument(TArg arg, string argName, int skipFrames); diff --git a/Package/Core/Promises/CompilerServices/PromiseAwaiters.cs b/Package/Core/Promises/CompilerServices/PromiseAwaiters.cs index eed811ec..5c215c94 100644 --- a/Package/Core/Promises/CompilerServices/PromiseAwaiters.cs +++ b/Package/Core/Promises/CompilerServices/PromiseAwaiters.cs @@ -119,7 +119,7 @@ static PromiseNoThrowAwaiter() #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] #endif - public readonly partial struct PromiseAwaiterVoid : ICriticalNotifyCompletion, Internal.IPromiseAwaiter + public readonly partial struct PromiseAwaiterVoid : ICriticalNotifyCompletion, Internal.IPromiseAwareAwaiter { private readonly Promise _promise; @@ -189,7 +189,7 @@ public void UnsafeOnCompleted(Action continuation) } [MethodImpl(Internal.InlineOption)] - void Internal.IPromiseAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) + void Internal.IPromiseAwareAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) => asyncPromiseRef.HookupAwaiter(_promise._ref, _promise._id); static partial void ValidateArgument(TArg arg, string argName, int skipFrames); @@ -206,7 +206,7 @@ static partial void ValidateArgument(TArg arg, string argName, int skipFra #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] #endif - public readonly partial struct PromiseAwaiter : ICriticalNotifyCompletion, Internal.IPromiseAwaiter + public readonly partial struct PromiseAwaiter : ICriticalNotifyCompletion, Internal.IPromiseAwareAwaiter { private readonly Promise _promise; @@ -275,7 +275,7 @@ public void UnsafeOnCompleted(Action continuation) => OnCompleted(continuation); [MethodImpl(Internal.InlineOption)] - void Internal.IPromiseAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) + void Internal.IPromiseAwareAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) => asyncPromiseRef.HookupAwaiter(_promise._ref, _promise._id); static partial void ValidateArgument(TArg arg, string argName, int skipFrames); @@ -292,7 +292,7 @@ static partial void ValidateArgument(TArg arg, string argName, int skipFra #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] #endif - public readonly partial struct PromiseNoThrowAwaiterVoid : ICriticalNotifyCompletion, Internal.IPromiseAwaiter + public readonly partial struct PromiseNoThrowAwaiterVoid : ICriticalNotifyCompletion, Internal.IPromiseAwareAwaiter { private readonly Promise _promise; @@ -360,7 +360,7 @@ public void UnsafeOnCompleted(Action continuation) => OnCompleted(continuation); [MethodImpl(Internal.InlineOption)] - void Internal.IPromiseAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) + void Internal.IPromiseAwareAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) => asyncPromiseRef.HookupAwaiter(_promise._ref, _promise._id); /// @@ -386,7 +386,7 @@ static partial void ValidateArgument(TArg arg, string argName, int skipFra #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] #endif - public readonly partial struct PromiseNoThrowAwaiter : ICriticalNotifyCompletion, Internal.IPromiseAwaiter + public readonly partial struct PromiseNoThrowAwaiter : ICriticalNotifyCompletion, Internal.IPromiseAwareAwaiter { private readonly Promise _promise; @@ -454,7 +454,7 @@ public void UnsafeOnCompleted(Action continuation) => OnCompleted(continuation); [MethodImpl(Internal.InlineOption)] - void Internal.IPromiseAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) + void Internal.IPromiseAwareAwaiter.AwaitOnCompletedInternal(Internal.PromiseRefBase asyncPromiseRef) => asyncPromiseRef.HookupAwaiter(_promise._ref, _promise._id); /// diff --git a/Package/Core/Promises/Config.cs b/Package/Core/Promises/Config.cs index 4b39a520..5c011089 100644 --- a/Package/Core/Promises/Config.cs +++ b/Package/Core/Promises/Config.cs @@ -156,7 +156,8 @@ public static bool AsyncFlowExecutionContextEnabled s_asyncFlowExecutionContextEnabled = true; } } - private static bool s_asyncFlowExecutionContextEnabled; + // Internal so that tests can disable it directly. + internal static bool s_asyncFlowExecutionContextEnabled; [MethodImpl(MethodImplOptions.NoInlining)] private static void ThrowCannotDisableAsyncFlow() diff --git a/Package/Core/Promises/Internal/AsValueTaskInternal.cs b/Package/Core/Promises/Internal/AsValueTaskInternal.cs index 3c301c43..d9d92678 100644 --- a/Package/Core/Promises/Internal/AsValueTaskInternal.cs +++ b/Package/Core/Promises/Internal/AsValueTaskInternal.cs @@ -113,7 +113,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) } else { - var exception = state == Promise.State.Rejected ? handler._rejectContainer.GetValueAsException() : Promise.CancelException(); + var exception = state == Promise.State.Rejected ? handler.RejectContainer.GetValueAsException() : Promise.CancelException(); handler.MaybeDispose(); _core.SetException(exception); } diff --git a/Package/Core/Promises/Internal/AsyncInternal.cs b/Package/Core/Promises/Internal/AsyncInternal.cs index 128ea3f3..31ebf80f 100644 --- a/Package/Core/Promises/Internal/AsyncInternal.cs +++ b/Package/Core/Promises/Internal/AsyncInternal.cs @@ -32,8 +32,6 @@ partial class Internal partial class PromiseRefBase { - internal virtual void ContinueAsyncFunction() => throw new System.InvalidOperationException(); - [MethodImpl(InlineOption)] internal void HookupAwaiter(PromiseRefBase awaiter, short promiseId) { @@ -42,6 +40,29 @@ internal void HookupAwaiter(PromiseRefBase awaiter, short promiseId) awaiter.HookupExistingWaiter(promiseId, this); } + [MethodImpl(InlineOption)] + internal void HookupAwaiterWithContext(PromiseRefBase awaiter, short promiseId, SynchronizationContext synchronizationContext) + { + ValidateAwait(awaiter, promiseId); + + if (awaiter == null) + { + // The awaited promise was already complete, and the await was configured to continue asynchronously. + ContinueOnContext(synchronizationContext); + return; + } + + var context = ContinuationContext; + ContinuationContext = context == null + ? (object) synchronizationContext + : ConfiguredAwaitDualContext.GetOrCreate(synchronizationContext, context.UnsafeAs()); + + this.SetPrevious(awaiter); + awaiter.HookupExistingWaiter(promiseId, this); + } + + protected virtual void ContinueOnContext(SynchronizationContext synchronizationContext) => throw new System.InvalidOperationException(); + #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] #endif @@ -72,7 +93,7 @@ internal void SetException(Exception exception) } else { - _rejectContainer = CreateRejectContainer(exception, int.MinValue, null, this); + RejectContainer = CreateRejectContainer(exception, int.MinValue, null, this); HandleNextInternal(Promise.State.Rejected); } } @@ -101,9 +122,9 @@ internal static void AwaitOnCompleted(ref TAwaiter awai #if NETCOREAPP // These checks and cast are eliminated by the JIT. #pragma warning disable IDE0038 // Use pattern matching - if (null != default(TAwaiter) && awaiter is IPromiseAwaiter) + if (null != default(TAwaiter) && awaiter is IPromiseAwareAwaiter) { - ((IPromiseAwaiter) awaiter).AwaitOnCompletedInternal(_ref); + ((IPromiseAwareAwaiter) awaiter).AwaitOnCompletedInternal(_ref); } else { @@ -125,9 +146,9 @@ internal static void AwaitUnsafeOnCompleted(ref TAwaite #if NETCOREAPP // These checks and cast are eliminated by the JIT. #pragma warning disable IDE0038 // Use pattern matching - if (null != default(TAwaiter) && awaiter is IPromiseAwaiter) + if (null != default(TAwaiter) && awaiter is IPromiseAwareAwaiter) { - ((IPromiseAwaiter) awaiter).AwaitOnCompletedInternal(_ref); + ((IPromiseAwareAwaiter) awaiter).AwaitOnCompletedInternal(_ref); } else { @@ -139,7 +160,7 @@ internal static void AwaitUnsafeOnCompleted(ref TAwaite CriticalAwaitOverrider.AwaitOnCompleted(ref awaiter, _ref, _ref.MoveNext); #endif } - } + } // class AsyncPromiseRef #if !OPTIMIZED_ASYNC_MODE sealed partial class AsyncPromiseRef @@ -178,9 +199,6 @@ public static PromiseMethodContinuer GetOrCreate(ref TStateMachin #endif private sealed partial class Continuer : PromiseMethodContinuer where TStateMachine : IAsyncStateMachine { - private static readonly ContextCallback s_executionContextCallback = state - => state.UnsafeAs>()._stateMachine.MoveNext(); - private Continuer() { _moveNext = ContinueMethod; @@ -218,13 +236,14 @@ private void ContinueMethod() try #endif { - if (_owner._executionContext != null) + var continuationContext = _owner.ContinuationContext; + if (continuationContext == null) { - ExecutionContext.Run(_owner._executionContext, s_executionContextCallback, this); + _stateMachine.MoveNext(); } else { - _stateMachine.MoveNext(); + ContinueOnContext(continuationContext); } } #if PROMISE_DEBUG @@ -234,6 +253,34 @@ private void ContinueMethod() } #endif } + + private void ContinueOnContext(object continuationContext) + { + if (continuationContext is SynchronizationContext synchronizationContext) + { + _owner.ContinuationContext = null; + ScheduleContextCallback(synchronizationContext, this, + obj => obj.UnsafeAs>()._stateMachine.MoveNext(), + obj => obj.UnsafeAs>()._stateMachine.MoveNext()); + } + // TODO: Make ConfiguredAwaitDualContext inherit SynchronizationContext to eliminate an extra type check. + else if (continuationContext is ConfiguredAwaitDualContext dualContext) + { + _owner.ContinuationContext = dualContext._executionContext; + synchronizationContext = dualContext._synchronizationContext; + dualContext.Dispose(); + ScheduleContextCallback(synchronizationContext, this, + obj => obj.UnsafeAs>().ContinueMethod(), + obj => obj.UnsafeAs>().ContinueMethod()); + } + else + { + _owner.ContinuationContext = null; + ExecutionContext.Run(continuationContext.UnsafeAs(), + obj => obj.UnsafeAs>()._stateMachine.MoveNext(), + this); + } + } } } @@ -250,7 +297,7 @@ private static void SetStateMachine(ref TStateMachine stateMachin } if (Promise.Config.AsyncFlowExecutionContextEnabled) { - _ref._executionContext = ExecutionContext.Capture(); + _ref.ContinuationContext = ExecutionContext.Capture(); } } @@ -262,7 +309,6 @@ internal override void MaybeDispose() _continuer.Dispose(); _continuer = null; } - _executionContext = null; ObjectPool.MaybeRepool(this); } @@ -274,13 +320,11 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) _continuer.MoveNext.Invoke(); } - internal override void ContinueAsyncFunction() - { - ThrowIfInPool(this); - this.SetPrevious(null); - _continuer.MoveNext.Invoke(); - } - } // class AsyncPromiseRef + protected override void ContinueOnContext(SynchronizationContext synchronizationContext) + => ScheduleContextCallback(synchronizationContext, _continuer.MoveNext, + obj => obj.UnsafeAs().Invoke(), + obj => obj.UnsafeAs().Invoke()); + } // class AsyncPromiseRef #else // !OPTIMIZED_ASYNC_MODE @@ -291,9 +335,6 @@ partial class AsyncPromiseRef #endif private sealed partial class AsyncPromiseRefMachine : AsyncPromiseRef where TStateMachine : IAsyncStateMachine { - private static readonly ContextCallback s_executionContextCallback = state - => state.UnsafeAs>()._stateMachine.MoveNext(); - private AsyncPromiseRefMachine() { _moveNext = Continue; @@ -322,20 +363,20 @@ internal override void MaybeDispose() { Dispose(); _stateMachine = default; - _executionContext = null; ObjectPool.MaybeRepool(this); } [MethodImpl(InlineOption)] private void Continue() { - if (_executionContext != null) + var continuationContext = ContinuationContext; + if (continuationContext == null) { - ExecutionContext.Run(_executionContext, s_executionContextCallback, this); + _stateMachine.MoveNext(); } else { - _stateMachine.MoveNext(); + ContinueOnContext(continuationContext); } } @@ -346,11 +387,47 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) Continue(); } - internal override void ContinueAsyncFunction() + private void ContinueOnContext(object continuationContext) { - ThrowIfInPool(this); - Continue(); + if (continuationContext is SynchronizationContext synchronizationContext) + { + ContinuationContext = null; + ScheduleContextCallback(synchronizationContext, this, + obj => obj.UnsafeAs>()._stateMachine.MoveNext(), + obj => obj.UnsafeAs>()._stateMachine.MoveNext()); + } + // TODO: Make ConfiguredAwaitDualContext inherit SynchronizationContext to eliminate an extra type check. + else if (continuationContext is ConfiguredAwaitDualContext dualContext) + { + ContinuationContext = dualContext._executionContext; + synchronizationContext = dualContext._synchronizationContext; + dualContext.Dispose(); + ScheduleContextCallback(synchronizationContext, this, + obj => obj.UnsafeAs>().ContinueWithExecutionContext(), + obj => obj.UnsafeAs>().ContinueWithExecutionContext()); + } + else + { + ContinuationContext = null; + ExecutionContext.Run(continuationContext.UnsafeAs(), + obj => obj.UnsafeAs>()._stateMachine.MoveNext(), + this); + } + } + + private void ContinueWithExecutionContext() + { + var continuationContext = ContinuationContext; + ContinuationContext = null; + ExecutionContext.Run(continuationContext.UnsafeAs(), + obj => obj.UnsafeAs>()._stateMachine.MoveNext(), + this); } + + protected override void ContinueOnContext(SynchronizationContext synchronizationContext) + => ScheduleContextCallback(synchronizationContext, this, + obj => obj.UnsafeAs>().Continue(), + obj => obj.UnsafeAs>().Continue()); } private Action MoveNext @@ -370,17 +447,16 @@ private static void SetStateMachine(ref TStateMachine stateMachin } if (Promise.Config.AsyncFlowExecutionContextEnabled) { - _ref._executionContext = ExecutionContext.Capture(); + _ref.ContinuationContext = ExecutionContext.Capture(); } } internal override void MaybeDispose() { Dispose(); - _executionContext = null; ObjectPool.MaybeRepool(this); } - } + } // class AsyncPromiseRef #endif // OPTIMIZED_ASYNC_MODE } // class PromiseRef } // class Internal diff --git a/Package/Core/Promises/Internal/AwaitInternal.cs b/Package/Core/Promises/Internal/AwaitInternal.cs index 002889aa..8e7e2c39 100644 --- a/Package/Core/Promises/Internal/AwaitInternal.cs +++ b/Package/Core/Promises/Internal/AwaitInternal.cs @@ -35,7 +35,7 @@ internal ExceptionDispatchInfo GetExceptionDispatchInfo(Promise.State state, sho if (state == Promise.State.Rejected) { SuppressRejection = true; - var exceptionDispatchInfo = _rejectContainer.GetExceptionDispatchInfo(); + var exceptionDispatchInfo = RejectContainer.GetExceptionDispatchInfo(); MaybeDispose(); return exceptionDispatchInfo; } @@ -64,7 +64,7 @@ internal Promise.ResultContainer GetResultContainerAndMaybeDispose(short promise [MethodImpl(InlineOption)] internal Promise.ResultContainer GetResultContainerAndMaybeDispose() { - var resultContainer = new Promise.ResultContainer(_rejectContainer, State); + var resultContainer = new Promise.ResultContainer(RejectContainer, State); SuppressRejection = true; MaybeDispose(); return resultContainer; @@ -101,7 +101,7 @@ internal TResult GetResultAndMaybeDispose() [MethodImpl(InlineOption)] new internal Promise.ResultContainer GetResultContainerAndMaybeDispose() { - var resultContainer = new Promise.ResultContainer(_result, _rejectContainer, State); + var resultContainer = new Promise.ResultContainer(_result, RejectContainer, State); SuppressRejection = true; MaybeDispose(); return resultContainer; @@ -173,7 +173,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) } } - internal interface IPromiseAwaiter + internal interface IPromiseAwareAwaiter { void AwaitOnCompletedInternal(PromiseRefBase asyncPromiseRef); } @@ -209,7 +209,7 @@ internal static void AwaitOnCompleted(ref TAwaiter awaiter, PromiseRefBase async => s_awaitFunc(ref awaiter, asyncPromiseRef, continuation); } - internal unsafe static class AwaitOverriderImpl where TAwaiter : struct, ICriticalNotifyCompletion, IPromiseAwaiter + internal unsafe static class AwaitOverriderImpl where TAwaiter : struct, ICriticalNotifyCompletion, IPromiseAwareAwaiter { [MethodImpl(InlineOption)] internal static void Create() @@ -260,7 +260,7 @@ internal static void AwaitOnCompleted(ref TAwaiter awaiter, PromiseRefBase async } } - internal sealed class AwaitOverriderImpl : AwaitOverrider where TAwaiter : struct, ICriticalNotifyCompletion, IPromiseAwaiter + internal sealed class AwaitOverriderImpl : AwaitOverrider where TAwaiter : struct, ICriticalNotifyCompletion, IPromiseAwareAwaiter { [MethodImpl(InlineOption)] internal static void Create() diff --git a/Package/Core/Promises/Internal/CancelInternal.cs b/Package/Core/Promises/Internal/CancelInternal.cs index c4a5b348..a73b6ff9 100644 --- a/Package/Core/Promises/Internal/CancelInternal.cs +++ b/Package/Core/Promises/Internal/CancelInternal.cs @@ -17,7 +17,7 @@ internal virtual void MaybeReportUnhandledAndDispose(Promise.State state) { // PromiseSingleAwait - MaybeReportUnhandledRejection(_rejectContainer, state); + MaybeReportUnhandledRejection(state); MaybeDispose(); } @@ -272,7 +272,7 @@ protected override void Execute(PromiseRefBase handler, Promise.State state, ref } else if (state == Promise.State.Rejected) { - var rejectContainer = handler._rejectContainer; + var rejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.MaybeDispose(); _cancelationHelper.TryRelease(); @@ -363,7 +363,7 @@ protected override void Execute(PromiseRefBase handler, Promise.State state, ref handler.SuppressRejection = true; _cancelationHelper.TryRelease(); invokingRejected = true; - rejectCallback.InvokeRejecter(handler, handler._rejectContainer, this); + rejectCallback.InvokeRejecter(handler, handler.RejectContainer, this); } else { @@ -424,7 +424,7 @@ protected override void Execute(PromiseRefBase handler, Promise.State state, ref { handler.SuppressRejection = true; _cancelationHelper.TryRelease(); - _continuer.Invoke(handler, handler._rejectContainer, state, this); + _continuer.Invoke(handler, handler.RejectContainer, state, this); } else { @@ -494,7 +494,7 @@ protected override void Execute(PromiseRefBase handler, Promise.State state, ref { handler.SuppressRejection = true; _cancelationHelper.TryRelease(); - callback.Invoke(handler, handler._rejectContainer, state, this); + callback.Invoke(handler, handler.RejectContainer, state, this); } else { diff --git a/Package/Core/Promises/Internal/ConfiguredPromise.cs b/Package/Core/Promises/Internal/ConfiguredPromise.cs index 5dc6fa37..dc0536c7 100644 --- a/Package/Core/Promises/Internal/ConfiguredPromise.cs +++ b/Package/Core/Promises/Internal/ConfiguredPromise.cs @@ -13,7 +13,7 @@ namespace Proto.Promises { partial class Internal { - partial class PromiseRefBase : HandleablePromiseBase, ITraceable + partial class PromiseRefBase { #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] @@ -80,7 +80,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) ThrowIfInPool(this); handler.SetCompletionState(state); - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; _result = handler.GetResult(); _tempState = state; @@ -259,65 +259,49 @@ private void HandleFromContext() #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] #endif - internal sealed partial class ConfiguredAsyncPromiseContinuer : HandleablePromiseBase + internal sealed partial class ConfiguredAwaitDualContext : HandleablePromiseBase { - private SynchronizationContext _context; + internal SynchronizationContext _synchronizationContext; + internal ExecutionContext _executionContext; - private ConfiguredAsyncPromiseContinuer() { } + private ConfiguredAwaitDualContext() { } [MethodImpl(InlineOption)] - private static ConfiguredAsyncPromiseContinuer GetOrCreate() + private static ConfiguredAwaitDualContext GetOrCreate() { - var obj = ObjectPool.TryTakeOrInvalid(); + var obj = ObjectPool.TryTakeOrInvalid(); return obj == InvalidAwaitSentinel.s_instance - ? new ConfiguredAsyncPromiseContinuer() - : obj.UnsafeAs(); + ? new ConfiguredAwaitDualContext() + : obj.UnsafeAs(); } - internal static void ConfigureAsyncContinuation(PromiseRefBase asyncPromiseRef, SynchronizationContext context, PromiseRefBase awaiter, short promiseId) + [MethodImpl(InlineOption)] + internal static ConfiguredAwaitDualContext GetOrCreate(SynchronizationContext synchronizationContext, ExecutionContext executionContext) { #if PROMISE_DEBUG || PROTO_PROMISE_DEVELOPER_MODE - if (context == null) + if (synchronizationContext == null) { - throw new InvalidOperationException("context cannot be null"); + throw new System.InvalidOperationException("synchronizationContext cannot be null"); } -#endif - - asyncPromiseRef.ValidateAwait(awaiter, promiseId); - asyncPromiseRef.SetPrevious(awaiter); - - if (awaiter == null) + if (executionContext == null) { - ScheduleContextCallback(context, asyncPromiseRef, - obj => obj.UnsafeAs().ContinueAsyncFunction(), - obj => obj.UnsafeAs().ContinueAsyncFunction() - ); - return; + throw new System.InvalidOperationException("executionContext cannot be null"); } +#endif - var continuer = GetOrCreate(); - continuer._next = asyncPromiseRef; - continuer._context = context; - - awaiter.HookupNewWaiter(promiseId, continuer); + var context = GetOrCreate(); + context._synchronizationContext = synchronizationContext; + context._executionContext = executionContext; + return context; } - internal override void Handle(PromiseRefBase handler, Promise.State state) + internal void Dispose() { - ThrowIfInPool(this); - handler.SetCompletionState(state); - - var asyncPromiseRef = _next; - var context = _context; - _context = null; + _synchronizationContext = null; + _executionContext = null; ObjectPool.MaybeRepool(this); - - ScheduleContextCallback(context, asyncPromiseRef, - obj => obj.UnsafeAs().ContinueAsyncFunction(), - obj => obj.UnsafeAs().ContinueAsyncFunction() - ); } - } // class ConfiguredAsyncPromiseContinuer + } // class ConfiguredAwaitDualContext } // class PromiseRefBase } // class Internal } \ No newline at end of file diff --git a/Package/Core/Promises/Internal/DeferredInternal.cs b/Package/Core/Promises/Internal/DeferredInternal.cs index 7ad14327..872c7977 100644 --- a/Package/Core/Promises/Internal/DeferredInternal.cs +++ b/Package/Core/Promises/Internal/DeferredInternal.cs @@ -57,7 +57,7 @@ public bool TryIncrementDeferredId(int deferredId) public void RejectDirect(IRejectContainer reasonContainer) { - _rejectContainer = reasonContainer; + RejectContainer = reasonContainer; HandleNextInternal(Promise.State.Rejected); } diff --git a/Package/Core/Promises/Internal/DelegateWrappersInternal.cs b/Package/Core/Promises/Internal/DelegateWrappersInternal.cs index 58f99ccb..7d3010a3 100644 --- a/Package/Core/Promises/Internal/DelegateWrappersInternal.cs +++ b/Package/Core/Promises/Internal/DelegateWrappersInternal.cs @@ -491,7 +491,7 @@ private void InvokeRejecter(IRejectContainer rejectContainer, PromiseRefBase own } else { - owner._rejectContainer = rejectContainer; + owner.RejectContainer = rejectContainer; owner.HandleNextInternal(Promise.State.Rejected); } } @@ -563,7 +563,7 @@ private void InvokeRejecter(IRejectContainer rejectContainer, PromiseRefBase own } else { - owner._rejectContainer = rejectContainer; + owner.RejectContainer = rejectContainer; owner.HandleNextInternal(Promise.State.Rejected); } } @@ -712,7 +712,7 @@ void IDelegateRejectPromise.InvokeRejecter(PromiseRefBase handler, IRejectContai } else { - owner._rejectContainer = rejectContainer; + owner.RejectContainer = rejectContainer; owner.HandleNextInternal(Promise.State.Rejected); } } @@ -760,7 +760,7 @@ void IDelegateRejectPromise.InvokeRejecter(PromiseRefBase handler, IRejectContai } else { - owner._rejectContainer = rejectContainer; + owner.RejectContainer = rejectContainer; owner.HandleNextInternal(Promise.State.Rejected); } } @@ -1328,7 +1328,7 @@ private void InvokeRejecter(IRejectContainer rejectContainer, PromiseRefBase own } else { - owner._rejectContainer = rejectContainer; + owner.RejectContainer = rejectContainer; owner.HandleNextInternal(Promise.State.Rejected); } } @@ -1402,7 +1402,7 @@ private void InvokeRejecter(IRejectContainer rejectContainer, PromiseRefBase own } else { - owner._rejectContainer = rejectContainer; + owner.RejectContainer = rejectContainer; owner.HandleNextInternal(Promise.State.Rejected); } } @@ -1557,7 +1557,7 @@ void IDelegateRejectPromise.InvokeRejecter(PromiseRefBase handler, IRejectContai } else { - owner._rejectContainer = rejectContainer; + owner.RejectContainer = rejectContainer; owner.HandleNextInternal(Promise.State.Rejected); } } @@ -1607,7 +1607,7 @@ void IDelegateRejectPromise.InvokeRejecter(PromiseRefBase handler, IRejectContai } else { - owner._rejectContainer = rejectContainer; + owner.RejectContainer = rejectContainer; owner.HandleNextInternal(Promise.State.Rejected); } } diff --git a/Package/Core/Promises/Internal/MergeInternal.cs b/Package/Core/Promises/Internal/MergeInternal.cs index 9f831df6..b06b5350 100644 --- a/Package/Core/Promises/Internal/MergeInternal.cs +++ b/Package/Core/Promises/Internal/MergeInternal.cs @@ -362,7 +362,7 @@ protected void MarkReady(uint totalWaiters, ref int waitCount, Promise.State sta if (_isComplete == 0) { _next = PromiseCompletionSentinel.s_instance; - SetCompletionState(_rejectContainer == null ? stateIfComplete : Promise.State.Rejected); + SetCompletionState(RejectContainer == null ? stateIfComplete : Promise.State.Rejected); } break; } @@ -476,7 +476,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state, int i } if (isComplete) { - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.MaybeDispose(); InterlockedAddWithUnsignedOverflowCheck(ref _retainCounter, -1); @@ -496,7 +496,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) : TrySetComplete(handler); if (isComplete) { - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.MaybeDispose(); InterlockedAddWithUnsignedOverflowCheck(ref _retainCounter, -1); diff --git a/Package/Core/Promises/Internal/ParallelAsyncInternal.cs b/Package/Core/Promises/Internal/ParallelAsyncInternal.cs index e140ea9e..8a967e25 100644 --- a/Package/Core/Promises/Internal/ParallelAsyncInternal.cs +++ b/Package/Core/Promises/Internal/ParallelAsyncInternal.cs @@ -55,7 +55,6 @@ internal sealed partial class PromiseParallelForEachAsync _exceptions; @@ -85,7 +84,7 @@ internal static PromiseParallelForEachAsync GetOrCreate( var promise = GetOrCreate(); promise.Reset(); promise._body = body; - promise._synchronizationContext = synchronizationContext ?? BackgroundSynchronizationContextSentinel.s_instance; + promise.ContinuationContext = synchronizationContext ?? BackgroundSynchronizationContextSentinel.s_instance; promise._remainingAvailableWorkers = maxDegreeOfParallelism; promise._completionState = Promise.State.Resolved; promise._stopExecuting = false; @@ -106,7 +105,6 @@ internal override void MaybeDispose() ValidateNoPending(); Dispose(); _body = default; - _synchronizationContext = null; _executionContext = null; ObjectPool.MaybeRepool(this); } @@ -161,7 +159,7 @@ private bool ExitLockAndGetLaunchNext() if ((int) newValue > 0) { // Another worker is waiting on the lock, schedule it on the context and jump to inside lock. - ScheduleContextCallback(_synchronizationContext, this, + ScheduleContextCallback(ContinuationContext.UnsafeAs(), this, obj => obj.UnsafeAs>().ExecuteWorkerInsideLock(), obj => obj.UnsafeAs>().ExecuteWorkerInsideLock() ); @@ -191,7 +189,7 @@ internal void MaybeLaunchWorker(bool launchWorker) // We add to the wait counter before we run the worker to resolve a race condition where the counter could hit zero prematurely. InterlockedAddWithUnsignedOverflowCheck(ref _waitCounter, 1); - ScheduleContextCallback(_synchronizationContext, this, + ScheduleContextCallback(ContinuationContext.UnsafeAs(), this, obj => obj.UnsafeAs>().ExecuteWorkerAndLaunchNext(), obj => obj.UnsafeAs>().ExecuteWorkerAndLaunchNext() ); @@ -354,7 +352,7 @@ private void WorkerBody(bool fromMoveNext) internal override void Handle(PromiseRefBase handler, Promise.State state) { RemoveComplete(handler); - var rejectContainer = handler._rejectContainer; + var rejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.SetCompletionState(state); handler.MaybeDispose(); @@ -368,7 +366,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) if (!isMoveNextAsyncContinuation) { // Schedule the worker body to run again on the context, but without launching another worker. - ScheduleContextCallback(_synchronizationContext, this, + ScheduleContextCallback(ContinuationContext.UnsafeAs(), this, obj => obj.UnsafeAs>().ExecuteWorkerWithoutLaunchNext(), obj => obj.UnsafeAs>().ExecuteWorkerWithoutLaunchNext() ); @@ -380,7 +378,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) return; } // Schedule the worker body to jump to after move next. - ScheduleContextCallback(_synchronizationContext, this, + ScheduleContextCallback(ContinuationContext.UnsafeAs(), this, obj => obj.UnsafeAs>().ExecuteWorkerAfterMoveNext(), obj => obj.UnsafeAs>().ExecuteWorkerAfterMoveNext() ); @@ -467,7 +465,7 @@ private void OnComplete() // This must be the very last thing done. if (_exceptions != null) { - _rejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); + RejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); _exceptions = null; HandleNextInternal(Promise.State.Rejected); } @@ -511,7 +509,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state, int i handler.SetCompletionState(state); if (state == Promise.State.Rejected) { - RecordException(handler._rejectContainer.GetValueAsException()); + RecordException(handler.RejectContainer.GetValueAsException()); handler.SuppressRejection = true; } handler.MaybeDispose(); diff --git a/Package/Core/Promises/Internal/ParallelInternal.cs b/Package/Core/Promises/Internal/ParallelInternal.cs index ef6eb723..084ee3a1 100644 --- a/Package/Core/Promises/Internal/ParallelInternal.cs +++ b/Package/Core/Promises/Internal/ParallelInternal.cs @@ -217,7 +217,6 @@ internal sealed partial class PromiseParallelForEach GetO promise.Reset(); promise._enumerator = enumerator; promise._body = body; - promise._synchronizationContext = synchronizationContext ?? BackgroundSynchronizationContextSentinel.s_instance; + promise.ContinuationContext = synchronizationContext ?? BackgroundSynchronizationContextSentinel.s_instance; promise._remainingAvailableWorkers = maxDegreeOfParallelism; promise._completionState = Promise.State.Resolved; promise._stopExecuting = false; @@ -260,7 +259,6 @@ internal override void MaybeDispose() ValidateNoPending(); Dispose(); _body = default; - _synchronizationContext = null; _executionContext = null; ObjectPool.MaybeRepool(this); } @@ -279,7 +277,7 @@ internal void MaybeLaunchWorker(bool launchWorker) // We add to the wait counter before we run the worker to resolve a race condition where the counter could hit zero prematurely. InterlockedAddWithUnsignedOverflowCheck(ref _waitCounter, 1); - ScheduleContextCallback(_synchronizationContext, this, + ScheduleContextCallback(ContinuationContext.UnsafeAs(), this, obj => obj.UnsafeAs>().ExecuteWorkerAndLaunchNext(), obj => obj.UnsafeAs>().ExecuteWorkerAndLaunchNext() ); @@ -374,7 +372,7 @@ private void WorkerBody(bool launchNext) internal override void Handle(PromiseRefBase handler, Promise.State state) { RemoveComplete(handler); - var rejectContainer = handler._rejectContainer; + var rejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.SetCompletionState(state); handler.MaybeDispose(); @@ -382,7 +380,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) if (state == Promise.State.Resolved) { // Schedule the worker body to run again on the context, but without launching another worker. - ScheduleContextCallback(_synchronizationContext, this, + ScheduleContextCallback(ContinuationContext.UnsafeAs(), this, obj => obj.UnsafeAs>().ExecuteWorkerWithoutLaunchNext(), obj => obj.UnsafeAs>().ExecuteWorkerWithoutLaunchNext() ); @@ -456,7 +454,7 @@ private void MaybeComplete() // This must be the very last thing done. if (_exceptions != null) { - _rejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); + RejectContainer = CreateRejectContainer(new AggregateException(_exceptions), int.MinValue, null, this); _exceptions = null; HandleNextInternal(Promise.State.Rejected); } diff --git a/Package/Core/Promises/Internal/PromiseFieldsInternal.cs b/Package/Core/Promises/Internal/PromiseFieldsInternal.cs index 36dfef19..43d71d13 100644 --- a/Package/Core/Promises/Internal/PromiseFieldsInternal.cs +++ b/Package/Core/Promises/Internal/PromiseFieldsInternal.cs @@ -20,7 +20,9 @@ using Proto.Promises.Collections; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Threading; namespace Proto.Promises @@ -91,13 +93,52 @@ partial class PromiseSynchronousWaiter : HandleablePromiseBase volatile private int _waitState; // int for Interlocked. } - partial class PromiseRefBase : HandleablePromiseBase + // We add a class between HandleablePromiseBase and PromiseRefBase so that we can have a union struct field without affecting derived types sizes. + // https://github.com/dotnet/runtime/issues/109680 +#if !PROTO_PROMISE_DEVELOPER_MODE + [DebuggerNonUserCode, StackTraceHidden] +#endif + internal abstract class PromiseRefBaseWithStructField : HandleablePromiseBase + { + // We union the fields together to save space. + // The field may contain the ExecutionContext or SynchronizationContext of the yielded `async Promise` while it is pending. + // When the promise is complete in a rejected state, it will contain the IRejectContainer. + [StructLayout(LayoutKind.Explicit)] + private struct ContextRejectUnion + { + // Common case this is null. If Promise.Config.AsyncFlowExecutionContextEnabled is true, this may be ExecutionContext. + // If an awaited Promise was configured, this may be SynchronizationContext. If both cases occurred, this will be ConfiguredAwaitDualContext. + [FieldOffset(0)] + internal object _continuationContext; + [FieldOffset(0)] + internal IRejectContainer _rejectContainer; + } + + private ContextRejectUnion _contextOrRejection; + + internal object ContinuationContext + { + [MethodImpl(InlineOption)] + get => _contextOrRejection._continuationContext; + [MethodImpl(InlineOption)] + set => _contextOrRejection._continuationContext = value; + } + + internal IRejectContainer RejectContainer + { + [MethodImpl(InlineOption)] + get => _contextOrRejection._rejectContainer; + [MethodImpl(InlineOption)] + set => _contextOrRejection._rejectContainer = value; + } + } + + partial class PromiseRefBase : PromiseRefBaseWithStructField { #if PROMISE_DEBUG CausalityTrace ITraceable.Trace { get; set; } internal PromiseRefBase _previous; // Used to detect circular awaits. #endif - internal IRejectContainer _rejectContainer; private short _promiseId = 1; // Start with Id 1 instead of 0 to reduce risk of false positives. volatile private Promise.State _state; @@ -434,12 +475,6 @@ partial class RacePromiseWithIndexGroup : RacePromiseGroupBase<(int, TR partial class AsyncPromiseRef : PromiseSingleAwait { - // TODO: change this field to object. Either store ExecutionContext or SynchronizationContext. - // If both contexts need to be used, use ConfiguredAsyncPromiseContinuer to wrap them both. - // We already null-check it, so it won't cost anything in the common case. If it's not null, then we proceed to type-check. - // This should improve performance of Promise.ConfigureAwait so that it can avoid allocating ConfiguredAsyncPromiseContinuer in the common case. - private ExecutionContext _executionContext; - #if !OPTIMIZED_ASYNC_MODE partial class PromiseMethodContinuer : HandleablePromiseBase { diff --git a/Package/Core/Promises/Internal/PromiseInternal.cs b/Package/Core/Promises/Internal/PromiseInternal.cs index d3e8ec12..af400dd0 100644 --- a/Package/Core/Promises/Internal/PromiseInternal.cs +++ b/Package/Core/Promises/Internal/PromiseInternal.cs @@ -185,12 +185,12 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] #endif - internal abstract partial class PromiseRefBase : HandleablePromiseBase, ITraceable + internal abstract partial class PromiseRefBase : PromiseRefBaseWithStructField, ITraceable { internal void HandleSelfWithoutResult(PromiseRefBase handler, Promise.State state) { ThrowIfInPool(this); - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.MaybeDispose(); HandleNextInternal(state); @@ -243,7 +243,6 @@ internal Promise.State State [MethodImpl(InlineOption)] private set => _state = value; } - internal bool SuppressRejection { [MethodImpl(InlineOption)] @@ -267,14 +266,10 @@ protected PromiseRefBase() { } if (!WasAwaitedOrForgotten) { // Promise was not awaited or forgotten. - string message = "A Promise's resources were garbage collected without it being awaited. You must await, return, or forget each promise. " + this; + string message = $"A Promise's resources were garbage collected without it being awaited. You must await, return, or forget each promise. {this}"; ReportRejection(new UnobservedPromiseException(message), this); } - if (State == Promise.State.Rejected & !SuppressRejection) - { - // Rejection maybe wasn't caught. - _rejectContainer?.ReportUnhandled(); - } + MaybeReportUnhandledRejection(State); } [MethodImpl(InlineOption)] @@ -326,7 +321,9 @@ private void Dispose() protected void IncrementPromiseIdAndClearPrevious() { IncrementPromiseId(); - _rejectContainer = null; + RejectContainer = null; + // RejectContainer shares a field with ContinuationContext. + //ContinuationContext = null; this.SetPrevious(null); } @@ -462,12 +459,12 @@ private HandleablePromiseBase ReadNextWaiterAndMaybeSetCompleted() return nextWaiter; } - private void MaybeReportUnhandledRejection(IRejectContainer rejectContainer, Promise.State state) + private void MaybeReportUnhandledRejection(Promise.State state) { if (state == Promise.State.Rejected & !SuppressRejection) { SuppressRejection = true; - rejectContainer.ReportUnhandled(); + RejectContainer.ReportUnhandled(); } } @@ -541,7 +538,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) handler.SetCompletionState(state); // Handler is disposed in Execute, so we need to cache the reject container in case of a RethrowException. - var rejectContainer = handler._rejectContainer; + var rejectContainer = handler.RejectContainer; bool invokingRejected = false; SetCurrentInvoker(this); try @@ -552,11 +549,11 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) { if (invokingRejected) { - _rejectContainer = rejectContainer; + RejectContainer = rejectContainer; } else { - _rejectContainer = CreateRejectContainer(e, int.MinValue, null, this); + RejectContainer = CreateRejectContainer(e, int.MinValue, null, this); state = Promise.State.Rejected; } HandleNextInternal(state); @@ -567,7 +564,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) } catch (Exception e) { - _rejectContainer = CreateRejectContainer(e, int.MinValue, null, this); + RejectContainer = CreateRejectContainer(e, int.MinValue, null, this); HandleNextInternal(Promise.State.Rejected); } ClearCurrentInvoker(); @@ -645,7 +642,7 @@ internal override void MaybeDispose() _nextBranches.Dispose(); // Rejection maybe wasn't caught. // We handle this directly here because we don't add the PromiseForgetSentinel to this type when it is forgotten. - MaybeReportUnhandledRejection(_rejectContainer, State); + MaybeReportUnhandledRejection(State); Dispose(); } ObjectPool.MaybeRepool(this); @@ -738,7 +735,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) { ThrowIfInPool(this); handler.SetCompletionState(state); - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; _result = handler.GetResult(); SetCompletionState(state); @@ -906,7 +903,7 @@ private void Run() } catch (Exception e) { - _rejectContainer = CreateRejectContainer(e, int.MinValue, null, this); + RejectContainer = CreateRejectContainer(e, int.MinValue, null, this); HandleNextInternal(Promise.State.Rejected); } ClearCurrentInvoker(); @@ -970,7 +967,7 @@ private void Run() } catch (Exception e) { - _rejectContainer = CreateRejectContainer(e, int.MinValue, null, this); + RejectContainer = CreateRejectContainer(e, int.MinValue, null, this); HandleNextInternal(Promise.State.Rejected); } ClearCurrentInvoker(); @@ -1249,7 +1246,7 @@ protected override void Execute(PromiseRefBase handler, Promise.State state, ref } else if (state == Promise.State.Rejected) { - var rejectContainer = handler._rejectContainer; + var rejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.MaybeDispose(); invokingRejected = true; @@ -1317,7 +1314,7 @@ protected override void Execute(PromiseRefBase handler, Promise.State state, ref { handler.SuppressRejection = true; invokingRejected = true; - rejectCallback.InvokeRejecter(handler, handler._rejectContainer, this); + rejectCallback.InvokeRejecter(handler, handler.RejectContainer, this); } else { @@ -1363,7 +1360,7 @@ protected override void Execute(PromiseRefBase handler, Promise.State state, ref handler.SuppressRejection = true; var callback = _continuer; _continuer = default; - callback.Invoke(handler, handler._rejectContainer, state, this); + callback.Invoke(handler, handler.RejectContainer, state, this); } } @@ -1411,7 +1408,7 @@ protected override void Execute(PromiseRefBase handler, Promise.State state, ref var callback = _continuer; _continuer = default; handler.SuppressRejection = true; - callback.Invoke(handler, handler._rejectContainer, state, this); + callback.Invoke(handler, handler.RejectContainer, state, this); } } @@ -1452,7 +1449,7 @@ protected override void Execute(PromiseRefBase handler, Promise.State state, ref var callback = _finalizer; _finalizer = default; _result = handler.GetResult(); - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.MaybeDispose(); try @@ -1464,8 +1461,8 @@ protected override void Execute(PromiseRefBase handler, Promise.State state, ref // Unlike normal finally clauses, we don't swallow the previous rejection. Instead, we report it. if (state == Promise.State.Rejected) { - _rejectContainer.ReportUnhandled(); - _rejectContainer = null; // Null it out in case it's a canceled exception. + RejectContainer.ReportUnhandled(); + RejectContainer = null; // Null it out in case it's a canceled exception. } throw; } @@ -1515,7 +1512,7 @@ protected override void Execute(PromiseRefBase handler, Promise.State state, ref } _result = handler.GetResult(); - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.MaybeDispose(); var callback = _finalizer; @@ -1530,8 +1527,8 @@ protected override void Execute(PromiseRefBase handler, Promise.State state, ref if (state == Promise.State.Rejected) { // Unlike normal finally clauses, we don't swallow the previous rejection. Instead, we report it. - _rejectContainer.ReportUnhandled(); - _rejectContainer = null; // Null it out in case it's a canceled exception. + RejectContainer.ReportUnhandled(); + RejectContainer = null; // Null it out in case it's a canceled exception. } throw; } @@ -1551,9 +1548,9 @@ private void HandleFromReturnedPromise(PromiseRefBase handler, Promise.State sta if (_previousState == Promise.State.Rejected) { // Unlike normal finally clauses, we don't swallow the previous rejection. Instead, we report it. - _rejectContainer.ReportUnhandled(); + RejectContainer.ReportUnhandled(); } - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; } handler.SuppressRejection = true; handler.MaybeDispose(); diff --git a/Package/Core/Promises/Internal/PromiseRetainerInternal.cs b/Package/Core/Promises/Internal/PromiseRetainerInternal.cs index 75bfa894..ce2baa47 100644 --- a/Package/Core/Promises/Internal/PromiseRetainerInternal.cs +++ b/Package/Core/Promises/Internal/PromiseRetainerInternal.cs @@ -85,7 +85,7 @@ internal override void MaybeDispose() _nextBranches.Dispose(); // Rejection maybe wasn't caught. // We handle this directly here because we don't add the PromiseForgetSentinel to this type when it is disposed. - MaybeReportUnhandledRejection(_rejectContainer, State); + MaybeReportUnhandledRejection(State); Dispose(); ObjectPool.MaybeRepool(this); } @@ -166,7 +166,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) { ThrowIfInPool(this); handler.SetCompletionState(state); - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; _result = handler.GetResult(); SetCompletionState(state); diff --git a/Package/Core/Promises/Internal/RaceInternal.cs b/Package/Core/Promises/Internal/RaceInternal.cs index defe186d..89a3f45d 100644 --- a/Package/Core/Promises/Internal/RaceInternal.cs +++ b/Package/Core/Promises/Internal/RaceInternal.cs @@ -56,7 +56,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) if (TrySetComplete(handler)) { _result = handler.GetResult(); - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.MaybeDispose(); InterlockedAddWithUnsignedOverflowCheck(ref _retainCounter, -1); @@ -111,7 +111,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state, int i if (TrySetComplete(handler)) { _result = index; - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.MaybeDispose(); InterlockedAddWithUnsignedOverflowCheck(ref _retainCounter, -1); @@ -166,7 +166,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state, int i if (TrySetComplete(handler)) { _result = (index, handler.GetResult()); - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.MaybeDispose(); InterlockedAddWithUnsignedOverflowCheck(ref _retainCounter, -1); @@ -236,7 +236,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state) bool isComplete = state == Promise.State.Resolved ? TrySetComplete(handler) : RemoveWaiterAndGetIsComplete(handler); - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; if (isComplete) { @@ -294,7 +294,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state, int i bool isComplete = handler.State == Promise.State.Resolved ? TrySetComplete(handler) : RemoveWaiterAndGetIsComplete(handler); - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; if (isComplete) { @@ -352,7 +352,7 @@ internal override void Handle(PromiseRefBase handler, Promise.State state, int i bool isComplete = handler.State == Promise.State.Resolved ? TrySetComplete(handler) : RemoveWaiterAndGetIsComplete(handler); - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; if (isComplete) { diff --git a/Package/Core/Promises/Internal/SentinelsInternal.cs b/Package/Core/Promises/Internal/SentinelsInternal.cs index 6fee1933..889545d5 100644 --- a/Package/Core/Promises/Internal/SentinelsInternal.cs +++ b/Package/Core/Promises/Internal/SentinelsInternal.cs @@ -13,7 +13,7 @@ namespace Proto.Promises { partial class Internal { - internal abstract partial class PromiseRefBase : HandleablePromiseBase, ITraceable + internal abstract partial class PromiseRefBase { #if !PROTO_PROMISE_DEVELOPER_MODE [DebuggerNonUserCode, StackTraceHidden] diff --git a/Package/Core/Promises/PromiseStaticMergeSettled.cs b/Package/Core/Promises/PromiseStaticMergeSettled.cs index 76bbcc38..69110d13 100644 --- a/Package/Core/Promises/PromiseStaticMergeSettled.cs +++ b/Package/Core/Promises/PromiseStaticMergeSettled.cs @@ -15,7 +15,7 @@ public partial struct Promise { [MethodImpl(Internal.InlineOption)] private static void GetAllResultContainer(Internal.PromiseRefBase handler, int index, ref IList result) - => result[index] = new ResultContainer(handler._rejectContainer, handler.State); + => result[index] = new ResultContainer(handler.RejectContainer, handler.State); #if NETCOREAPP || UNITY_2021_2_OR_NEWER private static unsafe Internal.GetResultDelegate> GetAllResultContainerFunc @@ -283,10 +283,10 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item1 = new ResultContainer(handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item2 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -336,10 +336,10 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item2 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -389,10 +389,10 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; } } @@ -447,13 +447,13 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item1 = new ResultContainer(handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item2 = new ResultContainer(handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -506,13 +506,13 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item2 = new ResultContainer(handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -565,13 +565,13 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -624,13 +624,13 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; } } @@ -687,16 +687,16 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item1 = new ResultContainer(handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item2 = new ResultContainer(handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -751,16 +751,16 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item2 = new ResultContainer(handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -815,16 +815,16 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -879,16 +879,16 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -944,16 +944,16 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; } } @@ -1013,19 +1013,19 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item1 = new ResultContainer(handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item2 = new ResultContainer(handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -1082,19 +1082,19 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item2 = new ResultContainer(handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -1151,19 +1151,19 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -1220,19 +1220,19 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -1290,19 +1290,19 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -1360,19 +1360,19 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item5 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; } } @@ -1434,22 +1434,22 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item1 = new ResultContainer(handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item2 = new ResultContainer(handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item6 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -1509,22 +1509,22 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item2 = new ResultContainer(handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item6 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -1584,22 +1584,22 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item6 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -1659,22 +1659,22 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item6 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -1734,22 +1734,22 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item6 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -1809,22 +1809,22 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item5 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item6 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -1884,22 +1884,22 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item5 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item6 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; } } @@ -1963,25 +1963,25 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item1 = new ResultContainer(handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item2 = new ResultContainer(handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item6 = new ResultContainer(handler.RejectContainer, handler.State); break; case 6: - result.Item7 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item7 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -2043,25 +2043,25 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item2 = new ResultContainer(handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item6 = new ResultContainer(handler.RejectContainer, handler.State); break; case 6: - result.Item7 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item7 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -2123,25 +2123,25 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item3 = new ResultContainer(handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item6 = new ResultContainer(handler.RejectContainer, handler.State); break; case 6: - result.Item7 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item7 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -2203,25 +2203,25 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item4 = new ResultContainer(handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item6 = new ResultContainer(handler.RejectContainer, handler.State); break; case 6: - result.Item7 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item7 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -2283,25 +2283,25 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item5 = new ResultContainer(handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item6 = new ResultContainer(handler.RejectContainer, handler.State); break; case 6: - result.Item7 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item7 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -2363,25 +2363,25 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item5 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item6 = new ResultContainer(handler.RejectContainer, handler.State); break; case 6: - result.Item7 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item7 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -2443,25 +2443,25 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item5 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item6 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 6: - result.Item7 = new ResultContainer(handler._rejectContainer, handler.State); + result.Item7 = new ResultContainer(handler.RejectContainer, handler.State); break; } } @@ -2523,25 +2523,25 @@ private static void GetMergeResult(Internal.PromiseRefBase handler, int index, r switch (index) { case 0: - result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item1 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 1: - result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item2 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 2: - result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item3 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 3: - result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item4 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 4: - result.Item5 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item5 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 5: - result.Item6 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item6 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; case 6: - result.Item7 = new Promise.ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + result.Item7 = new Promise.ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); break; } } diff --git a/Package/Core/Promises/PromiseTStatic.cs b/Package/Core/Promises/PromiseTStatic.cs index 2dc37883..03a8de91 100644 --- a/Package/Core/Promises/PromiseTStatic.cs +++ b/Package/Core/Promises/PromiseTStatic.cs @@ -604,7 +604,7 @@ public static Promise> All(TEnumerator promises, IList [MethodImpl(Internal.InlineOption)] private static void GetAllResultContainer(Internal.PromiseRefBase handler, int index, ref IList result) - => result[index] = new ResultContainer(handler.GetResult(), handler._rejectContainer, handler.State); + => result[index] = new ResultContainer(handler.GetResult(), handler.RejectContainer, handler.State); #if NETCOREAPP || UNITY_2021_2_OR_NEWER private static unsafe Internal.GetResultDelegate> GetAllResultContainerFunc diff --git a/Package/Core/Threading/Internal/AsyncLockInternal.cs b/Package/Core/Threading/Internal/AsyncLockInternal.cs index b23098b4..a876b6a2 100644 --- a/Package/Core/Threading/Internal/AsyncLockInternal.cs +++ b/Package/Core/Threading/Internal/AsyncLockInternal.cs @@ -211,7 +211,7 @@ internal override PromiseRefBase AddWaiter(short promiseId, HandleablePromiseBas void IAsyncLockPromise.Reject(IRejectContainer rejectContainer) { _cancelationRegistration.Dispose(); - _rejectContainer = rejectContainer; + RejectContainer = rejectContainer; _tempState = Promise.State.Rejected; // Notify the lock so this will be placed on the ready queue to re-acquire the lock before continuing. _lock.NotifyAbandonedConditionVariable(this); diff --git a/Package/Core/Threading/Internal/AsyncSynchronizationPromisesInternal.cs b/Package/Core/Threading/Internal/AsyncSynchronizationPromisesInternal.cs index c6d371b0..a73267dd 100644 --- a/Package/Core/Threading/Internal/AsyncSynchronizationPromisesInternal.cs +++ b/Package/Core/Threading/Internal/AsyncSynchronizationPromisesInternal.cs @@ -22,7 +22,6 @@ partial class PromiseRefBase #endif internal abstract class AsyncSynchronizationPromiseBase : PromiseSingleAwait, ICancelable { - private SynchronizationContext _continuationContext; protected CancelationRegistration _cancelationRegistration; // We have to store the state in a separate field until the next awaiter is ready to be invoked on the proper context. protected Promise.State _tempState; @@ -31,7 +30,7 @@ internal abstract class AsyncSynchronizationPromiseBase : PromiseSingle protected void Reset(bool continueOnCapturedContext) { Reset(); - _continuationContext = continueOnCapturedContext ? ContinuationOptions.CaptureContext() : null; + ContinuationContext = continueOnCapturedContext ? ContinuationOptions.CaptureContext() : null; // Assume the resolved state will occur. If this is actually canceled or rejected, the state will be set at that time. _tempState = Promise.State.Resolved; } @@ -39,21 +38,23 @@ protected void Reset(bool continueOnCapturedContext) new protected void Dispose() { base.Dispose(); - _continuationContext = null; _cancelationRegistration = default; } + [MethodImpl(InlineOption)] protected void Continue() + => Continue(ContinuationContext); + + private void Continue(object continuationContext) { - var context = _continuationContext; - if (context == null) + if (continuationContext == null) { // This was configured to continue synchronously. HandleNextInternal(_tempState); return; } - // This was configured to continuation on the context. - ScheduleContextCallback(context, this, + // This was configured to continue on the context. + ScheduleContextCallback(continuationContext.UnsafeAs(), this, obj => obj.UnsafeAs>().HandleFromContext(), obj => obj.UnsafeAs>().HandleFromContext() ); @@ -79,9 +80,11 @@ internal bool HookupAndGetIsCanceled(CancelationToken cancelationToken) internal void Reject(IRejectContainer rejectContainer) { _cancelationRegistration.Dispose(); - _rejectContainer = rejectContainer; + // ContinuationContext shares a field with RejectContainer, so we have to read it before writing. + var continuationContext = ContinuationContext; + RejectContainer = rejectContainer; _tempState = Promise.State.Rejected; - Continue(); + Continue(continuationContext); } internal void CancelDirect() diff --git a/Package/Core/Utilities/Internal/AsyncLazyInternal.cs b/Package/Core/Utilities/Internal/AsyncLazyInternal.cs index 7288521d..d2eb9735 100644 --- a/Package/Core/Utilities/Internal/AsyncLazyInternal.cs +++ b/Package/Core/Utilities/Internal/AsyncLazyInternal.cs @@ -143,7 +143,7 @@ internal override void Handle(Internal.PromiseRefBase handler, Promise.State sta { handler.SetCompletionState(state); _result = handler.GetResult(); - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.MaybeDispose(); OnComplete(state); @@ -260,7 +260,7 @@ internal override void Handle(Internal.PromiseRefBase handler, Promise.State sta { handler.SetCompletionState(state); _result = handler.GetResult(); - _rejectContainer = handler._rejectContainer; + RejectContainer = handler.RejectContainer; handler.SuppressRejection = true; handler.MaybeDispose(); OnComplete(state); @@ -335,7 +335,7 @@ protected void Start(Func> factory) } catch (Exception e) { - _rejectContainer = CreateRejectContainer(e, int.MinValue, null, this); + RejectContainer = CreateRejectContainer(e, int.MinValue, null, this); OnComplete(Promise.State.Rejected); } ClearCurrentInvoker(); @@ -356,7 +356,7 @@ protected void Start(Func> factory, ProgressToke } catch (Exception e) { - _rejectContainer = CreateRejectContainer(e, int.MinValue, null, this); + RejectContainer = CreateRejectContainer(e, int.MinValue, null, this); OnComplete(Promise.State.Rejected); } ClearCurrentInvoker(); @@ -382,7 +382,7 @@ void IWaitForCompleteHandler.HandleHookup(PromiseRefBase handler) { var state = handler.State; _owner._result = handler.GetResult(); - _owner._rejectContainer = handler._rejectContainer; + _owner.RejectContainer = handler.RejectContainer; _owner.SuppressRejection = true; handler.MaybeDispose(); _owner.OnComplete(state); diff --git a/Package/Tests/CoreTests/APIs/ConfigureAwaitTests.cs b/Package/Tests/CoreTests/APIs/ConfigureAwaitTests.cs index 1ccb9ec8..bfc2146f 100644 --- a/Package/Tests/CoreTests/APIs/ConfigureAwaitTests.cs +++ b/Package/Tests/CoreTests/APIs/ConfigureAwaitTests.cs @@ -45,8 +45,9 @@ private static IEnumerable GetArgs() foreach (CompletedContinuationBehavior completedBehavior in Enum.GetValues(typeof(CompletedContinuationBehavior))) foreach (bool alreadyComplete in new[] { true, false }) foreach (SynchronizationType completeContext in alreadyComplete ? foregroundOnlyContext : completeContexts) + foreach (bool asyncFlowExecutionContext in new[] { true, false }) { - yield return new TestCaseData(completeType, continuationContext, completedBehavior, alreadyComplete, completeContext); + yield return new TestCaseData(completeType, continuationContext, completedBehavior, alreadyComplete, completeContext, asyncFlowExecutionContext); } } @@ -56,8 +57,12 @@ public void ContinuationsWillBeInvokedOnTheCorrectSynchronizationContext_void( SynchronizationType continuationContext, CompletedContinuationBehavior completedBehavior, bool alreadyComplete, - SynchronizationType completeContext) + SynchronizationType completeContext, + bool asyncFlowExecutionContext) { + // Normally AsyncFlowExecutionContextEnabled cannot be disabled after it is enabled, but we need to test both configurations. + Promise.Config.s_asyncFlowExecutionContextEnabled = asyncFlowExecutionContext; + var foregroundThread = Thread.CurrentThread; var threadHelper = new ThreadHelper(); @@ -108,8 +113,12 @@ public void ContinuationsWillBeInvokedOnTheCorrectSynchronizationContext_T( SynchronizationType continuationContext, CompletedContinuationBehavior completedBehavior, bool alreadyComplete, - SynchronizationType completeContext) + SynchronizationType completeContext, + bool asyncFlowExecutionContext) { + // Normally AsyncFlowExecutionContextEnabled cannot be disabled after it is enabled, but we need to test both configurations. + Promise.Config.s_asyncFlowExecutionContextEnabled = asyncFlowExecutionContext; + var foregroundThread = Thread.CurrentThread; var threadHelper = new ThreadHelper(); @@ -162,8 +171,12 @@ public void ForceAsync_ContinuationWillBeInvokedProperly_void( #endif )] SynchronizationType continuationContext, [Values] CompletedContinuationBehavior completedBehavior, - [Values] bool alreadyComplete) + [Values] bool alreadyComplete, + [Values] bool asyncFlowExecutionContext) { + // Normally AsyncFlowExecutionContextEnabled cannot be disabled after it is enabled, but we need to test both configurations. + Promise.Config.s_asyncFlowExecutionContextEnabled = asyncFlowExecutionContext; + var foregroundThread = Thread.CurrentThread; var continuationOptions = TestHelper.GetContinuationOptions(continuationContext, completedBehavior); @@ -219,8 +232,12 @@ public void ForceAsync_ContinuationWillBeInvokedProperly_T( #endif )] SynchronizationType continuationContext, [Values] CompletedContinuationBehavior completedBehavior, - [Values] bool alreadyComplete) + [Values] bool alreadyComplete, + [Values] bool asyncFlowExecutionContext) { + // Normally AsyncFlowExecutionContextEnabled cannot be disabled after it is enabled, but we need to test both configurations. + Promise.Config.s_asyncFlowExecutionContextEnabled = asyncFlowExecutionContext; + var foregroundThread = Thread.CurrentThread; var continuationOptions = TestHelper.GetContinuationOptions(continuationContext, completedBehavior);