Skip to content

Commit 9c2cf0f

Browse files
committed
misc: Add CacheInstances
1 parent 4fcc24b commit 9c2cf0f

2 files changed

Lines changed: 72 additions & 0 deletions

File tree

devito/ir/support/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from .vector import * # noqa
22
from .utils import * # noqa
33
from .basic import * # noqa
4+
from .caching import * # noqa
45
from .space import * # noqa
56
from .guards import * # noqa
67
from .syncs import * # noqa

devito/ir/support/caching.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from collections.abc import Callable
2+
from functools import lru_cache
3+
from typing import TypeVar
4+
5+
6+
__all__ = ['CacheInstances', 'CacheInstancesMeta']
7+
8+
9+
# Describes the type of a subclass of CacheInstances
10+
InstanceType = TypeVar('InstanceType', bound='CacheInstances', covariant=True)
11+
12+
13+
class CacheInstancesMeta(type):
14+
"""
15+
Metaclass to wrap construction in an LRU cache.
16+
"""
17+
18+
_cache_clear_funcs: dict[type, Callable[[], None]] = {}
19+
20+
def __init__(cls: type[InstanceType], *args) -> None: # type: ignore
21+
super().__init__(*args)
22+
23+
# Define an instance cache attribute and register a cache clear function
24+
cls._instance_cache: Callable | None = None
25+
CacheInstancesMeta._cache_clear_funcs[cls] = cls._clear_cache
26+
27+
def __call__(cls: type[InstanceType], # type: ignore
28+
*args, **kwargs) -> InstanceType:
29+
if cls._instance_cache is None:
30+
maxsize = getattr(cls, '_instance_cache_size', 128)
31+
cls._instance_cache = lru_cache(maxsize=maxsize)(super().__call__)
32+
33+
args, kwargs = cls._preprocess_args(*args, **kwargs)
34+
return cls._instance_cache(*args, **kwargs)
35+
36+
@classmethod
37+
def clear_caches(cls: type['CacheInstancesMeta']) -> None:
38+
"""
39+
Clear all caches for classes using this metaclass.
40+
"""
41+
for clear_func in cls._cache_clear_funcs.values():
42+
clear_func()
43+
44+
45+
class CacheInstances(metaclass=CacheInstancesMeta):
46+
"""
47+
Parent class that wraps construction in an LRU cache.
48+
"""
49+
50+
@classmethod
51+
def _preprocess_args(cls, *args, **kwargs):
52+
"""
53+
Preprocess the arguments before caching. This can be overridden in subclasses
54+
to customize argument handling (e.g. to convert to hashable types).
55+
"""
56+
return args, kwargs
57+
58+
@classmethod
59+
def _clear_cache(cls) -> None:
60+
"""
61+
Clears the cache for this class, if any has been initialized.
62+
"""
63+
if cls._instance_cache is not None:
64+
cls._instance_cache.cache_clear() # type: ignore
65+
66+
@staticmethod
67+
def clear_caches() -> None:
68+
"""
69+
Clears all IR instance caches.
70+
"""
71+
CacheInstancesMeta.clear_caches()

0 commit comments

Comments
 (0)