summaryrefslogtreecommitdiffstats
path: root/src/pybind/mgr/dashboard/plugins/lru_cache.py
blob: 9b29a60124475636525567af7cb9e9568c9eee5d (plain)
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
# -*- coding: utf-8 -*-
"""
This is a minimal implementation of lru_cache function.

Based on Python 3 functools and backports.functools_lru_cache.
"""
from __future__ import absolute_import

from collections import OrderedDict
from functools import wraps
from threading import RLock


def lru_cache(maxsize=128, typed=False):
    if typed is not False:
        raise NotImplementedError("typed caching not supported")

    def decorating_function(function):
        cache = OrderedDict()
        stats = [0, 0]
        rlock = RLock()
        setattr(function, 'cache_info', lambda:
                "hits={}, misses={}, maxsize={}, currsize={}".format(
                    stats[0], stats[1], maxsize, len(cache)))

        @wraps(function)
        def wrapper(*args, **kwargs):
            key = args + tuple(kwargs.items())
            with rlock:
                if key in cache:
                    ret = cache[key]
                    del cache[key]
                    cache[key] = ret
                    stats[0] += 1
                else:
                    ret = function(*args, **kwargs)
                    if len(cache) == maxsize:
                        cache.popitem(last=False)
                    cache[key] = ret
                    stats[1] += 1
            return ret

        return wrapper
    return decorating_function