@@ -15,7 +15,7 @@ class ContinuationProcessor<T> : IContinuationProcessor where T : IAwaitInstruct
1515 public static ContinuationProcessor < T > instance ;
1616
1717 T [ ] currentQueue , futureQueue ;
18- int futureCount , maxIndex ;
18+ int currentCount , currentIndex , futureCount , maxIndex ;
1919
2020 public ContinuationProcessor ( int capacity )
2121 {
@@ -29,38 +29,47 @@ public ContinuationProcessor(int capacity)
2929
3030 public void Process ( )
3131 {
32- int count = futureCount ;
32+ currentCount = futureCount ;
3333 futureCount = 0 ;
3434
3535 // swap queues
3636 var tmp = currentQueue ;
3737 currentQueue = futureQueue ;
3838 futureQueue = tmp ;
3939
40- for ( int i = 0 ; i < count ; ++ i )
40+ for ( ; currentIndex < currentCount ; ++ currentIndex )
4141 {
42- ref var c = ref currentQueue [ i ] ;
42+ ref var c = ref currentQueue [ currentIndex ] ;
4343
4444 if ( ! c . Evaluate ( ) )
4545 {
46+ // this is hottest path so we don't do a bounds check here (see Add)
4647 futureQueue [ futureCount ] = c ;
4748 ++ futureCount ;
4849 }
4950 }
51+
52+ currentIndex = 0 ;
53+ currentCount = 0 ;
5054
51- Array . Clear ( currentQueue , 0 , count ) ;
55+ Array . Clear ( currentQueue , 0 , currentCount ) ;
5256 }
5357
5458 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
5559 public void Add ( in T cont )
5660 {
5761 try
5862 {
59- if ( futureCount >= maxIndex )
63+ // we might have awaiters yet to be processed this frame; when they are re-added we skip any
64+ // bounds checks as an optimisation, so we need to make sure the queue has enough space to
65+ // re-add them all in case none of them have finished
66+ int potentialFutureCount = futureCount + currentCount - currentIndex ;
67+
68+ if ( potentialFutureCount >= maxIndex )
6069 {
61- AssertQueueSize ( futureCount + 1 ) ;
70+ AssertQueueSize ( potentialFutureCount + 1 ) ;
6271
63- int newQueueSize = Math . Min ( MaxQueueSize , futureQueue . Length * 3 / 2 ) ;
72+ int newQueueSize = Math . Min ( MaxQueueSize , Math . Max ( potentialFutureCount , futureQueue . Length * 3 / 2 ) ) ;
6473
6574 Array . Resize ( ref futureQueue , newQueueSize ) ;
6675 Array . Resize ( ref currentQueue , newQueueSize ) ;
0 commit comments