88using System . Collections ;
99using System . Collections . Generic ;
1010using System . Diagnostics ;
11+ using System . Linq ;
1112using System . Runtime . InteropServices ;
1213using System . Security ;
1314using Xtensive . Core ;
@@ -34,7 +35,6 @@ public class WeakCache<TKey, TItem> :
3435 /// </summary>
3536 protected const int NoGcCount = 1024 ;
3637
37- private const int GcOperationCost = 2 ;
3838 private readonly bool trackResurrection ;
3939 private readonly Converter < TItem , TKey > keyExtractor ;
4040 private Dictionary < TKey , GCHandle > items ;
@@ -46,7 +46,7 @@ public class WeakCache<TKey, TItem> :
4646 public Converter < TItem , TKey > KeyExtractor
4747 {
4848 [ DebuggerStepThrough ]
49- get { return keyExtractor ; }
49+ get => keyExtractor ;
5050 }
5151
5252 /// <summary>
@@ -55,40 +55,32 @@ public Converter<TItem, TKey> KeyExtractor
5555 public bool TrackResurrection
5656 {
5757 [ DebuggerStepThrough ]
58- get { return trackResurrection ; }
58+ get => trackResurrection ;
5959 }
6060
6161 /// <inheritdoc/>
6262 public int Count
6363 {
6464 [ DebuggerStepThrough ]
65- get { return items . Count ; }
65+ get => items ? . Count ?? 0 ;
6666 }
6767
6868 #endregion
6969
7070 /// <inheritdoc/>
71- public TItem this [ TKey key , bool markAsHit ]
72- {
73- get {
74- TItem item ;
75- if ( TryGetItem ( key , markAsHit , out item ) )
76- return item ;
77- else
78- return null ;
79- }
80- }
71+ public TItem this [ TKey key , bool markAsHit ] => TryGetItem ( key , markAsHit , out var item ) ? item : null ;
8172
8273 /// <inheritdoc/>
8374 [ SecuritySafeCritical ]
8475 public virtual bool TryGetItem ( TKey key , bool markAsHit , out TItem item )
8576 {
8677 RegisterOperation ( 1 ) ;
87- GCHandle cached ;
88- if ( items . TryGetValue ( key , out cached ) ) {
89- item = ( TItem ) cached . Target ;
90- if ( item != null )
78+ if ( items != null && items . TryGetValue ( key , out var cached ) ) {
79+ item = ExtractTarget ( cached ) ;
80+ if ( item != null ) {
9181 return true ;
82+ }
83+
9284 items . Remove ( key ) ;
9385 cached . Free ( ) ;
9486 return false ;
@@ -98,113 +90,105 @@ public virtual bool TryGetItem(TKey key, bool markAsHit, out TItem item)
9890 }
9991
10092 /// <inheritdoc/>
101- public bool Contains ( TItem item )
102- {
103- return ContainsKey ( KeyExtractor ( item ) ) ;
104- }
93+ public bool Contains ( TItem item ) => ContainsKey ( KeyExtractor ( item ) ) ;
10594
10695 /// <inheritdoc/>
107- public bool ContainsKey ( TKey key )
108- {
109- TItem item ;
110- return TryGetItem ( key , false , out item ) ;
111- }
96+ public bool ContainsKey ( TKey key ) => TryGetItem ( key , false , out var _ ) ;
11297
11398 #region Modification methods: Add, Remove, Clear
11499
115100 /// <inheritdoc/>
116- public void Add ( TItem item )
117- {
118- Add ( item , true ) ;
119- }
101+ public void Add ( TItem item ) => Add ( item , true ) ;
102+
103+ private static Dictionary < TKey , GCHandle > CreateDictionary ( ) => new Dictionary < TKey , GCHandle > ( ) ;
120104
121105 /// <inheritdoc/>
122106 [ SecuritySafeCritical ]
123107 public virtual TItem Add ( TItem item , bool replaceIfExists )
124108 {
125- ArgumentValidator . EnsureArgumentNotNull ( item , " item" ) ;
109+ ArgumentValidator . EnsureArgumentNotNull ( item , nameof ( item ) ) ;
126110 RegisterOperation ( 2 ) ;
127111 var key = KeyExtractor ( item ) ;
128- GCHandle cached ;
129- if ( items . TryGetValue ( key , out cached ) ) {
130- if ( ! replaceIfExists ) {
131- var cachedItem = ( TItem ) cached . Target ;
132- if ( cachedItem != null )
133- return cachedItem ;
112+ if ( items == null ) {
113+ items = CreateDictionary ( ) ;
114+ }
115+ else if ( replaceIfExists ) {
116+ if ( items . Remove ( key , out var cached ) ) {
117+ cached . Free ( ) ;
118+ }
119+ }
120+ else if ( items . TryGetValue ( key , out var cached ) ) {
121+ if ( ExtractTarget ( cached ) is TItem cachedItem ) {
122+ return cachedItem ;
134123 }
135124 items . Remove ( key ) ;
136125 cached . Free ( ) ;
137126 }
138- items [ key ] = GCHandle . Alloc ( item ,
139- trackResurrection ? GCHandleType . WeakTrackResurrection : GCHandleType . Weak ) ;
127+ items [ key ] = GCHandle . Alloc ( item , trackResurrection ? GCHandleType . WeakTrackResurrection : GCHandleType . Weak ) ;
140128 return item ;
141129 }
142130
143131 /// <inheritdoc/>
144132 public void Remove ( TItem item )
145133 {
146- ArgumentValidator . EnsureArgumentNotNull ( item , " item" ) ;
134+ ArgumentValidator . EnsureArgumentNotNull ( item , nameof ( item ) ) ;
147135 RemoveKey ( KeyExtractor ( item ) ) ;
148136 }
149137
150138 /// <inheritdoc/>
151139 [ SecuritySafeCritical ]
152140 public virtual void RemoveKey ( TKey key )
153141 {
154- GCHandle cached ;
155- if ( items . TryGetValue ( key , out cached ) ) {
156- items . Remove ( key ) ;
142+ if ( items != null && items . Remove ( key , out var cached ) == true ) {
157143 cached . Free ( ) ;
158144 }
159145 }
160146
161147 /// <inheritdoc/>
162- public void RemoveKey ( TKey key , bool removeCompletely )
163- {
164- RemoveKey ( key ) ;
165- }
148+ public void RemoveKey ( TKey key , bool removeCompletely ) => RemoveKey ( key ) ;
166149
167150 /// <inheritdoc/>
168151 [ SecuritySafeCritical ]
169152 public virtual void Clear ( )
170153 {
154+ if ( items == null ) {
155+ return ;
156+ }
171157 try {
172- foreach ( var pair in items )
158+ foreach ( var pair in items ) {
173159 try {
174160 pair . Value . Free ( ) ;
175161 }
176162 catch { }
163+ }
177164 }
178165 finally {
179- items = new Dictionary < TKey , GCHandle > ( ) ;
166+ items = null ;
180167 time = 0 ;
181168 }
182169 }
183170
184171 /// <inheritdoc/>
185- public void Invalidate ( )
186- {
187- Clear ( ) ;
188- }
172+ public void Invalidate ( ) => Clear ( ) ;
189173
190174 /// <inheritdoc/>
191175 [ SecuritySafeCritical ]
192176 public virtual void CollectGarbage ( )
193177 {
194- int count = items . Count ;
195- if ( count <= NoGcCount )
178+ var count = items ? . Count ?? 0 ;
179+ if ( count <= NoGcCount ) {
196180 return ;
181+ }
197182
198183 Exception error = null ;
199184 int removedCount = 0 ;
200185 try {
201186 // Filtering
202- var newItems = new Dictionary < TKey , GCHandle > ( ) ;
203- foreach ( var pair in items ) {
204- var cached = pair . Value ;
187+ var newItems = CreateDictionary ( ) ;
188+ foreach ( var ( key , cached ) in items ) {
205189 var item = cached . Target ;
206190 if ( item != null )
207- newItems . Add ( pair . Key , cached ) ;
191+ newItems . Add ( key , cached ) ;
208192 else
209193 cached . Free ( ) ;
210194 }
@@ -233,26 +217,19 @@ public virtual void CollectGarbage()
233217
234218 /// <inheritdoc/>
235219 [ DebuggerStepThrough ]
236- IEnumerator IEnumerable . GetEnumerator ( )
237- {
238- return GetEnumerator ( ) ;
239- }
220+ IEnumerator IEnumerable . GetEnumerator ( ) => GetEnumerator ( ) ;
240221
241222 /// <inheritdoc/>
242223 public virtual IEnumerator < TItem > GetEnumerator ( )
243224 {
244- foreach ( var pair in items ) {
245- var item = ExtractTarget ( pair . Value ) ;
246- if ( item != null )
225+ foreach ( var pair in items ?? Enumerable . Empty < KeyValuePair < TKey , GCHandle > > ( ) ) {
226+ if ( ExtractTarget ( pair . Value ) is TItem item )
247227 yield return item ;
248228 }
249229 }
250230
251231 [ SecuritySafeCritical ]
252- private static TItem ExtractTarget ( GCHandle handle )
253- {
254- return ( TItem ) handle . Target ;
255- }
232+ private static TItem ExtractTarget ( GCHandle handle ) => ( TItem ) handle . Target ;
256233
257234 #endregion
258235
@@ -261,11 +238,10 @@ private static TItem ExtractTarget(GCHandle handle)
261238 private void RegisterOperation ( int weight )
262239 {
263240 time += weight ;
264- var count = items . Count ;
265- if ( count <= NoGcCount )
266- return ;
267- if ( time > ( ( count << 1 ) + count ) )
241+ var count = items ? . Count ?? 0 ;
242+ if ( count > NoGcCount && time > ( count << 1 ) + count ) {
268243 CollectGarbage ( ) ;
244+ }
269245 }
270246
271247 #endregion
@@ -283,7 +259,6 @@ public WeakCache(bool trackResurrection, Converter<TItem, TKey> keyExtractor)
283259 ArgumentValidator . EnsureArgumentNotNull ( keyExtractor , "keyExtractor" ) ;
284260 this . trackResurrection = trackResurrection ;
285261 this . keyExtractor = keyExtractor ;
286- items = new Dictionary < TKey , GCHandle > ( 1024 ) ;
287262 }
288263
289264 // Dispose pattern
@@ -294,14 +269,7 @@ public WeakCache(bool trackResurrection, Converter<TItem, TKey> keyExtractor)
294269 [ SecuritySafeCritical ]
295270 protected virtual void Dispose ( bool disposing )
296271 {
297- if ( items != null ) {
298- try {
299- Clear ( ) ;
300- }
301- finally {
302- items = null ;
303- }
304- }
272+ Clear ( ) ;
305273 }
306274
307275 /// <summary>
0 commit comments