22// Licensed under the MIT License.
33
44using System ;
5+ using System . Collections ;
56using System . Collections . Generic ;
67using System . Diagnostics ;
78using System . Reflection ;
@@ -1960,39 +1961,32 @@ private struct CachedOnFirstUseColumnGenerator<T, TGenerator>
19601961 IVisibleDomainSensitiveProjection
19611962 where TGenerator : IProjection < int , T >
19621963 {
1963- const byte byteTrue = 1 ;
1964- const byte byteFalse = 0 ;
1965-
1966- private readonly T [ ] cache ;
1967- private readonly byte [ ] isCached ;
1968- private TGenerator generator ;
1964+ private readonly int rowCount ;
1965+ private readonly Lazy < Cache > lazyCache ;
1966+ private readonly TGenerator generator ;
19691967
19701968 public CachedOnFirstUseColumnGenerator ( int rowCount , TGenerator generator )
19711969 {
1972- this . cache = new T [ rowCount ] ;
1973- this . isCached = new byte [ rowCount ] ;
1970+ this . rowCount = rowCount ;
19741971 this . generator = generator ;
1972+
1973+ // Lazy is thread-safe by default
1974+ this . lazyCache = new Lazy < Cache > ( ( ) => new Cache ( new T [ rowCount ] , new BitArray ( rowCount ) ) ) ;
19751975 }
19761976
19771977 private void ResetCache ( )
19781978 {
1979- for ( int i = 0 ; i < this . cache . Length ; ++ i )
1979+ if ( this . lazyCache . IsValueCreated )
19801980 {
1981- this . isCached [ i ] = byteFalse ;
1981+ this . lazyCache . Value . Reset ( ) ;
19821982 }
19831983 }
19841984
19851985 public T this [ int value ]
19861986 {
19871987 get
19881988 {
1989- if ( this . isCached [ value ] != byteTrue )
1990- {
1991- this . cache [ value ] = this . generator [ value ] ;
1992- this . isCached [ value ] = byteTrue ;
1993- }
1994-
1995- return this . cache [ value ] ;
1989+ return this . lazyCache . Value . Get ( value , this . generator ) ;
19961990 }
19971991 }
19981992
@@ -2017,7 +2011,7 @@ public object Clone()
20172011 if ( this . DependsOnVisibleDomain )
20182012 {
20192013 return new CachedOnFirstUseColumnGenerator < T , TGenerator > (
2020- this . cache . Length ,
2014+ this . rowCount ,
20212015 this . generator . CloneIfVisibleDomainSensitive ( ) ) ;
20222016 }
20232017 else
@@ -2038,6 +2032,24 @@ public bool NotifyVisibleDomainChanged(IVisibleDomainRegion newVisibleDomain)
20382032 }
20392033
20402034 public bool DependsOnVisibleDomain => this . generator . DependsOnVisibleDomain ( ) ;
2035+
2036+ private readonly record struct Cache ( T [ ] Values , BitArray IsCached )
2037+ {
2038+ public void Reset ( )
2039+ {
2040+ this . IsCached . SetAll ( false ) ;
2041+ }
2042+
2043+ public T Get ( int index , TGenerator generator )
2044+ {
2045+ if ( ! this . IsCached [ index ] )
2046+ {
2047+ this . Values [ index ] = generator [ index ] ;
2048+ this . IsCached [ index ] = true ;
2049+ }
2050+ return this . Values [ index ] ;
2051+ }
2052+ }
20412053 }
20422054
20432055 private static class CacheVisibleDomainColumn
0 commit comments