1+ using System . Diagnostics ;
2+ using System . Runtime . CompilerServices ;
13using System . Runtime . InteropServices ;
24
35namespace DotNext . Threading ;
46
7+ using InlinedTokenList = ValueTuple < CancellationTokenRegistration , CancellationTokenRegistration , CancellationTokenRegistration > ;
8+
59partial class CancellationTokenMultiplexer
610{
711 private sealed class PooledCancellationTokenSource : LinkedCancellationTokenSource , IResettable
812 {
9- private const int Capacity = 3 ;
10- private ( CancellationTokenRegistration , CancellationTokenRegistration , CancellationTokenRegistration ) inlinedList ;
11- private byte inlinedTokenCount ;
13+ private static readonly int InlinedListCapacity = GetCapacity < InlinedTokenList > ( ) ;
14+
15+ private InlinedTokenList inlinedList ;
16+ private int inlinedTokenCount ;
1217 private List < CancellationTokenRegistration > ? extraTokens ;
1318 internal PooledCancellationTokenSource ? Next ;
1419
1520 public void Add ( CancellationToken token )
16- => Add ( ) = Attach( token ) ;
21+ => Add ( Attach ( token ) ) ;
1722
18- private ref CancellationTokenRegistration Add ( )
23+ private void Add ( CancellationTokenRegistration registration )
1924 {
20- Span < CancellationTokenRegistration > registrations ;
21- int index ;
22- if ( inlinedTokenCount < Capacity )
25+ if ( inlinedTokenCount < InlinedListCapacity )
2326 {
24- index = inlinedTokenCount ++ ;
25- registrations = inlinedList . AsSpan ( ) ;
27+ Unsafe . Add ( ref FirstInlinedRegistration , inlinedTokenCount ++ ) = registration;
2628 }
2729 else
2830 {
2931 extraTokens ??= new ( ) ;
30- index = extraTokens . Count ;
31- extraTokens . Add ( default ) ;
32- registrations = CollectionsMarshal . AsSpan ( extraTokens ) ;
32+ extraTokens . Add ( registration ) ;
3333 }
34-
35- return ref registrations [ index ] ;
3634 }
3735
36+ [ DebuggerBrowsable ( DebuggerBrowsableState . Never ) ]
37+ private ref CancellationTokenRegistration FirstInlinedRegistration
38+ => ref Unsafe . As < InlinedTokenList , CancellationTokenRegistration > ( ref inlinedList ) ;
39+
3840 public int Count => inlinedTokenCount + extraTokens ? . Count ?? 0 ;
3941
4042 public ref CancellationTokenRegistration this [ int index ]
4143 {
4244 get
4345 {
46+ Debug . Assert ( ( uint ) index < ( uint ) Count ) ;
47+
4448 Span < CancellationTokenRegistration > registrations ;
45- if ( index < Capacity )
49+ if ( index < InlinedListCapacity )
4650 {
4751 registrations = inlinedList . AsSpan ( ) ;
4852 }
4953 else
5054 {
5155 registrations = CollectionsMarshal . AsSpan ( extraTokens ) ;
52- index -= Capacity ;
56+ index -= InlinedListCapacity ;
5357 }
5458
5559 return ref registrations [ index ] ;
@@ -63,6 +67,10 @@ public void Reset()
6367 extraTokens ? . Clear ( ) ;
6468 }
6569
70+ private static int GetCapacity < T > ( )
71+ where T : struct , ITuple
72+ => default ( T ) . Length ;
73+
6674 protected override void Dispose ( bool disposing )
6775 {
6876 if ( disposing )
0 commit comments