@@ -18,12 +18,10 @@ private sealed class Pending { internal required K Key; internal required Task<V
1818 private Entry [ ] _entries ;
1919 private Pending ? _pending ;
2020
21- public Cache ( ) => _entries = new Entry [ 2 ] ;
22- public Cache ( int capacity ) => _entries = new Entry [ capacity < 2 ? 2 : BitOperations . RoundUpToPowerOf2 ( ( uint ) capacity ) ] ;
21+ public Cache ( int capacity = 2 ) => _entries = new Entry [ capacity <= 2 ? 2 : BitOperations . RoundUpToPowerOf2 ( ( uint ) capacity ) ] ;
2322
24- public Cache ( IEnumerable < KeyValuePair < K , V > > items )
23+ public Cache ( IEnumerable < KeyValuePair < K , V > > items ) : this ( )
2524 {
26- _entries = new Entry [ 2 ] ;
2725 foreach ( var ( k , v ) in items ) AddOrUpdate ( k , v ) ;
2826 }
2927
@@ -46,9 +44,10 @@ private void AddOrUpdate(K key, V value)
4644 entries [ i ] . Next = entries [ bucketIndex ] . Bucket - 1 ;
4745 entries [ i ] . Key = key ;
4846 entries [ i ] . Value = value ;
49- entries [ bucketIndex ] . Bucket = ++ _count ;
50- _version ++ ;
47+ entries [ bucketIndex ] . Bucket = _count + 1 ;
5148 _entries = entries ;
49+ _count ++ ;
50+ _version ++ ;
5251 }
5352
5453 [ MethodImpl ( MethodImplOptions . NoInlining ) ]
@@ -72,9 +71,9 @@ public ValueTask<V> GetOrAdd(K key, Func<K, Task<V>> factory)
7271
7372 public ValueTask < V > GetOrAdd < TState > ( K key , TState state , Func < K , TState , Task < V > > factory )
7473 {
74+ var hashCode = key . GetHashCode ( ) ;
7575 var version = Volatile . Read ( ref _version ) ;
7676 var entries = Volatile . Read ( ref _entries ) ;
77- var hashCode = key . GetHashCode ( ) ;
7877 var i = entries [ hashCode & ( entries . Length - 1 ) ] . Bucket - 1 ;
7978 while ( i >= 0 )
8079 {
@@ -128,8 +127,8 @@ public void Compact(Func<KeyValuePair<K, V>, bool> keep)
128127 }
129128 }
130129 _count = newIndex ;
131- _version ++ ;
132130 _entries = newEntries ;
131+ _version ++ ;
133132 }
134133 }
135134
@@ -191,8 +190,17 @@ private void RemovePending(Pending remove)
191190
192191 public IEnumerator < KeyValuePair < K , V > > GetEnumerator ( )
193192 {
194- for ( int i = 0 ; i < _count ; i ++ )
195- yield return new ( _entries [ i ] . Key , _entries [ i ] . Value ) ;
193+ var version = Volatile . Read ( ref _version ) ;
194+ var count = _count ;
195+ var entries = _entries ;
196+ if ( version != Volatile . Read ( ref _version ) )
197+ lock ( _lock )
198+ {
199+ count = _count ;
200+ entries = _entries ;
201+ }
202+ for ( int i = 0 ; i < count ; i ++ )
203+ yield return new ( entries [ i ] . Key , entries [ i ] . Value ) ;
196204 }
197205
198206 IEnumerator IEnumerable . GetEnumerator ( ) => GetEnumerator ( ) ;
0 commit comments