chr
2026-04-05 fe750b791d5b517cc4e9bc8e99a9a75139a0cfba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
using System;
using System.Collections.Immutable;
namespace OpenTap
{
    /// <summary> Cache class which clears when a certain criteria is met. </summary>
    internal class Cache<K, V>
    {
        // using immutable dictionary to avoid issues with race conditions.
        // note that for caches data races are not that important.
        ImmutableDictionary<K, V> dict = ImmutableDictionary<K, V>.Empty;
        
        // this function returns an object which is used for checking if the cache should be cleared.
        readonly Func<object> clearTrigger;
        
        // last object returned by clearTrigger.
        object currentObj;
 
        ///<summary> The current number of cached elements. </summary> 
        public int Count
        {
            get
            {
                CheckClear();
                return dict.Count;
            }
        }
 
        public Cache(Func<object> clearTrigger)
        {
            this.clearTrigger = clearTrigger;
            currentObj = clearTrigger();
        }
        
        void CheckClear()
        {
            var clearCheck = clearTrigger();
            if (Equals(clearCheck, currentObj) == false)
            {
                dict = ImmutableDictionary<K, V>.Empty;
                currentObj = clearTrigger();
            }
        }
 
        /// <summary> tries getting a value for a key. </summary>
        public bool TryGetValue(K key, out V value)
        {
            CheckClear();
            return dict.TryGetValue(key, out value);
        }
 
        public V AddValue(K key, V value)
        {
            CheckClear();
            dict = dict.SetItem(key, value);
            return value;
        }
    }
    
    class CacheObservable
    {
        public event EventHandler Updated; 
 
        public void OnUpdated()
        {
            Updated?.Invoke(this, EventArgs.Empty);
        }
    }
 
    internal class Cached<K>
    {
        readonly Func<K> getValue;
        K value;
        bool hasValue;
 
        public K GetValue()
        {
            if (!hasValue)
            {
                value = getValue();
                hasValue = true;
            }
            return value;
        }
        public Cached(CacheObservable cacheState, Func<K> getValue)
        {
            this.getValue = getValue;
            cacheState.Updated += CacheStateOnChange;
        }
        void CacheStateOnChange(object sender, EventArgs e)
        {
            hasValue = false;
        }
    }
}