@@ -435,64 +435,30 @@ private static unsafe T Suspend<T>(Task<T> task, ConfigureAwaitOptions options)
435435 return default ! ;
436436 }
437437
438- /// <summary>
439- /// Used by internal thunks that implement awaiting on ValueTask.
440- /// A ValueTask may wrap:
441- /// - Completed result (we never await this)
442- /// - Task
443- /// - ValueTaskSource
444- /// Therefore, when we are awaiting a ValueTask completion we are really
445- /// awaiting a completion of an underlying Task or ValueTaskSource.
446- /// </summary>
447- /// <param name="valueTask">ValueTask whose completion we are awaiting.</param>
448438 [ Intrinsic ]
449439 [ BypassReadyToRun ]
450440 [ MethodImpl ( MethodImplOptions . NoInlining | MethodImplOptions . Async ) ]
451- private static unsafe void TransparentSuspend ( ValueTask valueTask )
441+ private static unsafe void TransparentSuspend ( IValueTaskSource source , short token )
452442 {
453443 ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState ;
454444 Continuation ? sentinelContinuation = state . SentinelContinuation ??= new Continuation ( ) ;
455445
456- Continuation nextCont ;
457- object ? obj = valueTask . _obj ;
458- if ( obj is Task t )
446+ ValueTaskSourceContinuation ? vtsCont = state . CachedValueTaskSourceContinuation ;
447+ if ( vtsCont != null )
459448 {
460- RuntimeAsyncTaskContinuation ? taskCont = state . CachedTaskContinuation ;
461- if ( taskCont != null )
462- {
463- state . CachedTaskContinuation = null ;
464- }
465- else
466- {
467- taskCont = new RuntimeAsyncTaskContinuation ( ) ;
468- }
469-
470- taskCont . Initialize ( t ) ;
471- state . StackState ->TaskContinuation = taskCont ;
472- nextCont = taskCont ;
449+ state . CachedValueTaskSourceContinuation = null ;
473450 }
474451 else
475452 {
476- ValueTaskSourceContinuation ? vtsCont = state . CachedValueTaskSourceContinuation ;
477- if ( vtsCont != null )
478- {
479- state . CachedValueTaskSourceContinuation = null ;
480- }
481- else
482- {
483- vtsCont = new ValueTaskSourceContinuation ( ) ;
484- }
485-
486- Debug . Assert ( obj is IValueTaskSource ) ;
487- vtsCont . Initialize ( Unsafe . As < object , IValueTaskSource > ( ref obj ) , valueTask . _token ) ;
488- state . StackState ->ValueTaskSourceContinuation = vtsCont ;
489- nextCont = vtsCont ;
453+ vtsCont = new ValueTaskSourceContinuation ( ) ;
490454 }
491455
492- sentinelContinuation . Next = nextCont ;
456+ vtsCont . Initialize ( source , token ) ;
493457
458+ sentinelContinuation . Next = vtsCont ;
459+ state . StackState ->ValueTaskSourceContinuation = vtsCont ;
494460 state . CaptureContexts ( ) ;
495- AsyncSuspend ( nextCont ) ;
461+ AsyncSuspend ( vtsCont ) ;
496462 }
497463
498464 [ Intrinsic ]
@@ -536,50 +502,27 @@ private static unsafe void Suspend(IValueTaskSource source, short token, bool co
536502 [ Intrinsic ]
537503 [ BypassReadyToRun ]
538504 [ MethodImpl ( MethodImplOptions . NoInlining | MethodImplOptions . Async ) ]
539- private static unsafe T TransparentSuspend < T > ( ValueTask < T > valueTask )
505+ private static unsafe T TransparentSuspend < T > ( IValueTaskSource < T > source , short token )
540506 {
541507 ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState ;
542508 Continuation ? sentinelContinuation = state . SentinelContinuation ??= new Continuation ( ) ;
543509
544- Continuation nextCont ;
545- object ? obj = valueTask . _obj ;
546- if ( obj is Task < T > t )
510+ ValueTaskSourceContinuation ? vtsCont = state . CachedValueTaskSourceContinuation ;
511+ if ( vtsCont != null )
547512 {
548- RuntimeAsyncTaskContinuation ? taskCont = state . CachedTaskContinuation ;
549- if ( taskCont != null )
550- {
551- state . CachedTaskContinuation = null ;
552- }
553- else
554- {
555- taskCont = new RuntimeAsyncTaskContinuation ( ) ;
556- }
557-
558- taskCont . Initialize < T > ( t ) ;
559- state . StackState ->TaskContinuation = taskCont ;
560- nextCont = taskCont ;
513+ state . CachedValueTaskSourceContinuation = null ;
561514 }
562515 else
563516 {
564- ValueTaskSourceContinuation ? vtsCont = state . CachedValueTaskSourceContinuation ;
565- if ( vtsCont != null )
566- {
567- state . CachedValueTaskSourceContinuation = null ;
568- }
569- else
570- {
571- vtsCont = new ValueTaskSourceContinuation ( ) ;
572- }
573-
574- Debug . Assert ( obj is IValueTaskSource < T > ) ;
575- vtsCont . Initialize < T > ( Unsafe . As < object , IValueTaskSource < T > > ( ref obj ) , valueTask . _token ) ;
576- state . StackState ->ValueTaskSourceContinuation = vtsCont ;
577- nextCont = vtsCont ;
517+ vtsCont = new ValueTaskSourceContinuation ( ) ;
578518 }
579519
580- sentinelContinuation . Next = nextCont ;
520+ vtsCont . Initialize < T > ( source , token ) ;
521+
522+ sentinelContinuation . Next = vtsCont ;
523+ state . StackState ->ValueTaskSourceContinuation = vtsCont ;
581524 state . CaptureContexts ( ) ;
582- AsyncSuspend ( nextCont ) ;
525+ AsyncSuspend ( vtsCont ) ;
583526 return default ! ;
584527 }
585528
@@ -706,14 +649,35 @@ private static void TransparentAwait(Task task)
706649 [ MethodImpl ( MethodImplOptions . Async ) ]
707650 private static void TransparentAwait ( ValueTask task )
708651 {
709- if ( ! task . IsCompleted )
652+ object ? obj = task . _obj ;
653+ if ( obj == null )
654+ {
655+ return ;
656+ }
657+
658+ if ( obj is Task t )
659+ {
660+ if ( ! t . IsCompleted )
661+ {
662+ TailAwait ( ) ;
663+ TransparentSuspend ( t ) ;
664+ return ;
665+ }
666+
667+ TaskAwaiter . ValidateEnd ( t ) ;
668+ return ;
669+ }
670+
671+ Debug . Assert ( obj is IValueTaskSource ) ;
672+ IValueTaskSource vts = Unsafe . As < object , IValueTaskSource > ( ref obj ) ;
673+ if ( vts . GetStatus ( task . _token ) == ValueTaskSourceStatus . Pending )
710674 {
711675 TailAwait ( ) ;
712- TransparentSuspend ( task ) ;
676+ TransparentSuspend ( vts , task . _token ) ;
713677 return ;
714678 }
715679
716- task . ThrowIfCompletedUnsuccessfully ( ) ;
680+ vts . GetResult ( task . _token ) ;
717681 }
718682
719683 [ BypassReadyToRun ]
@@ -734,13 +698,33 @@ private static T TransparentAwait<T>(Task<T> task)
734698 [ MethodImpl ( MethodImplOptions . Async ) ]
735699 private static T TransparentAwait < T > ( ValueTask < T > task )
736700 {
737- if ( ! task . IsCompleted )
701+ object ? obj = task . _obj ;
702+ if ( obj == null )
703+ {
704+ return task . _result ! ;
705+ }
706+
707+ if ( obj is Task < T > t )
708+ {
709+ if ( ! t . IsCompleted )
710+ {
711+ TailAwait ( ) ;
712+ return TransparentSuspend ( t ) ;
713+ }
714+
715+ TaskAwaiter . ValidateEnd ( t ) ;
716+ return t . ResultOnSuccess ;
717+ }
718+
719+ Debug . Assert ( obj is IValueTaskSource < T > ) ;
720+ IValueTaskSource < T > vts = Unsafe . As < object , IValueTaskSource < T > > ( ref obj ) ;
721+ if ( vts . GetStatus ( task . _token ) == ValueTaskSourceStatus . Pending )
738722 {
739723 TailAwait ( ) ;
740- return TransparentSuspend ( task ) ;
724+ return TransparentSuspend ( vts , task . _token ) ;
741725 }
742726
743- return task . Result ;
727+ return vts . GetResult ( task . _token ) ;
744728 }
745729
746730 // Represents execution of a chain of suspended and resuming runtime
0 commit comments