[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/pythonnet/pythonnet/just/src/runtime/Util/ConcurrentLruCache.cs [Back]  [Original]

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;

namespace Python.Runtime;

internal sealed class ConcurrentLruCache where TKey : notnull
{
    readonly ConcurrentDictionary map = new();
    readonly LinkedList lru = new();
    readonly object gate = new();

    sealed record CacheItem(TKey Key, TValue Value);

    public ConcurrentLruCache(int capacity)
    {
        if (capacity  map.Count;

    public TValue GetOrAdd(TKey key, Func valueFactory)
    {
        if (valueFactory is null)
            throw new ArgumentNullException(nameof(valueFactory));

        if (TryGetValue(key, out var existing))
            return existing;

        var created = valueFactory(key);

        lock (gate)
        {
            if (map.TryGetValue(key, out var alreadyAdded))
            {
                MoveToFront(alreadyAdded);
                return alreadyAdded.Value.Value;
            }

            var item = new CacheItem(key, created);
            var node = new LinkedListNode(item);
            lru.AddFirst(node);
            map[key] = node;
            EvictOverflow();
            return created;
        }
    }

    public bool TryGetValue(TKey key, out TValue value)
    {
        if (map.TryGetValue(key, out var node))
        {
            lock (gate)
            {
                if (map.TryGetValue(key, out node))
                {
                    MoveToFront(node);
                    value = node.Value.Value;
                    return true;
                }
            }
        }

        value = default!;
        return false;
    }

    public void Clear()
    {
        lock (gate)
        {
            lru.Clear();
            map.Clear();
        }
    }

    void MoveToFront(LinkedListNode node)
    {
        if (ReferenceEquals(lru.First, node))
            return;

        lru.Remove(node);
        lru.AddFirst(node);
    }

    void EvictOverflow()
    {
        while (map.Count > Capacity)
        {
            var last = lru.Last;
            if (last is null)
                return;

            lru.RemoveLast();
            map.TryRemove(last.Value.Key, out _);
        }
    }
}

Web Proxy Viewer  |  New URL  |  Original Page