1+ /*----------------------------------------------------------
2+ This Source Code Form is subject to the terms of the
3+ Mozilla Public License, v.2.0. If a copy of the MPL
4+ was not distributed with this file, You can obtain one
5+ at http://mozilla.org/MPL/2.0/.
6+ ----------------------------------------------------------*/
7+
8+ using System ;
9+ using System . Collections . Generic ;
10+
11+ namespace ScriptEngine . Machine
12+ {
13+ public class LruCache < TKey , TValue >
14+ {
15+ private readonly int _capacity ;
16+
17+ private readonly Dictionary < TKey , LinkedListNode < CacheItem > > _index =
18+ new Dictionary < TKey , LinkedListNode < CacheItem > > ( ) ;
19+
20+ private readonly LinkedList < CacheItem > _list = new LinkedList < CacheItem > ( ) ;
21+
22+ public LruCache ( int capacity )
23+ {
24+ _capacity = capacity ;
25+ }
26+
27+ public bool IsEmpty ( ) => _index . Count == 0 ;
28+
29+ public void Clear ( )
30+ {
31+ _index . Clear ( ) ;
32+ _list . Clear ( ) ;
33+ }
34+
35+ public TValue GetOrAdd ( TKey key , Func < TKey , TValue > factory )
36+ {
37+ if ( _index . TryGetValue ( key , out var listNode ) )
38+ {
39+ _list . Remove ( listNode ) ;
40+ _list . AddFirst ( listNode ) ;
41+ return listNode . Value . Value ;
42+ }
43+
44+ if ( _index . Count == _capacity )
45+ {
46+ var keyOfOld = _list . Last . Value . Key ;
47+ _index . Remove ( keyOfOld ) ;
48+ _list . RemoveLast ( ) ;
49+ }
50+
51+ var newItem = _list . AddFirst ( CacheItem . Create ( key , factory ( key ) ) ) ;
52+ _index [ key ] = newItem ;
53+ return newItem . Value . Value ;
54+ }
55+
56+ private class CacheItem
57+ {
58+ public static CacheItem Create ( TKey key , TValue value ) =>
59+ new CacheItem ( key , value ) ;
60+
61+ private CacheItem ( TKey key , TValue value )
62+ {
63+ Key = key ;
64+ Value = value ;
65+ }
66+
67+ public TKey Key { get ; }
68+
69+ public TValue Value { get ; }
70+ }
71+ }
72+ }
0 commit comments