@@ -14,52 +14,6 @@ thread_local! {
14
14
static CACHE : RefCell <Cache > = RefCell :: new( Cache :: default ( ) ) ;
15
15
}
16
16
17
- /// Configure the caching and eviction behaviour.
18
- pub fn config ( config : Config ) {
19
- CACHE . with ( |cache| cache. borrow_mut ( ) . config = config) ;
20
- }
21
-
22
- /// Configuration for caching and eviction behaviour.
23
- pub struct Config {
24
- max_age : u32 ,
25
- }
26
-
27
- impl Config {
28
- /// The maximum number of evictions an entry can survive without having been
29
- /// used in between.
30
- ///
31
- /// Default: 5
32
- pub fn max_age ( mut self , age : u32 ) -> Self {
33
- self . max_age = age;
34
- self
35
- }
36
- }
37
-
38
- impl Default for Config {
39
- fn default ( ) -> Self {
40
- Self { max_age : 5 }
41
- }
42
- }
43
-
44
- /// Evict cache entries that haven't been used in a while.
45
- ///
46
- /// The eviction behaviour can be customized with the [`config`] function.
47
- /// Currently, comemo does not evict the cache automatically (this might
48
- /// change in the future).
49
- pub fn evict ( ) {
50
- CACHE . with ( |cache| {
51
- let mut cache = cache. borrow_mut ( ) ;
52
- let max = cache. config . max_age ;
53
- cache. map . retain ( |_, entries| {
54
- entries. retain_mut ( |entry| {
55
- entry. age += 1 ;
56
- entry. age <= max
57
- } ) ;
58
- !entries. is_empty ( )
59
- } ) ;
60
- } ) ;
61
- }
62
-
63
17
/// Execute a function or use a cached result for it.
64
18
pub fn memoized < In , Out , F > ( id : TypeId , input : In , func : F ) -> Out
65
19
where
@@ -76,55 +30,57 @@ where
76
30
( id, hash)
77
31
} ;
78
32
79
- // Check if there is a cached output.
80
- let mut borrow = cache. borrow_mut ( ) ;
81
- if let Some ( output) = borrow. lookup :: < In , Out > ( key, & input) {
82
- return output;
83
- }
84
-
85
- borrow. depth += 1 ;
86
- drop ( borrow) ;
87
-
88
33
// Point all tracked parts of the input to these constraints.
89
34
let constraint = In :: Constraint :: default ( ) ;
90
- let ( tracked, outer) = input. retrack ( & constraint) ;
35
+
36
+ // Check if there is a cached output.
37
+ if let Some ( constrained) = cache. borrow ( ) . lookup :: < In , Out > ( key, & input) {
38
+ // Add the cached constraints to the outer ones.
39
+ let ( _, outer) = input. retrack ( & constraint) ;
40
+ outer. join ( & constrained. constraint ) ;
41
+ return constrained. output . clone ( ) ;
42
+ }
91
43
92
44
// Execute the function with the new constraints hooked in.
93
- let output = func ( tracked) ;
45
+ let ( input, outer) = input. retrack ( & constraint) ;
46
+ let output = func ( input) ;
94
47
95
- // Add the new constraints to the previous outer ones.
48
+ // Add the new constraints to the outer ones.
96
49
outer. join ( & constraint) ;
97
50
98
51
// Insert the result into the cache.
99
- borrow = cache. borrow_mut ( ) ;
100
- borrow. insert :: < In , Out > ( key, constraint, output. clone ( ) ) ;
101
- borrow. depth -= 1 ;
52
+ cache. borrow_mut ( ) . insert :: < In , Out > ( key, constraint, output. clone ( ) ) ;
102
53
103
54
output
104
55
} )
105
56
}
106
57
58
+ /// Completely clear the cache.
59
+ pub fn clear ( ) {
60
+ CACHE . with ( |cache| cache. borrow_mut ( ) . map . clear ( ) ) ;
61
+ }
62
+
107
63
/// The global cache.
108
64
#[ derive( Default ) ]
109
65
struct Cache {
110
66
/// Maps from function IDs + hashes to memoized results.
111
67
map : HashMap < ( TypeId , u128 ) , Vec < Entry > > ,
112
- /// The current depth of the memoized call stack.
113
- depth : usize ,
114
- /// The current configuration.
115
- config : Config ,
116
68
}
117
69
118
70
impl Cache {
119
71
/// Look for a matching entry in the cache.
120
- fn lookup < In , Out > ( & mut self , key : ( TypeId , u128 ) , input : & In ) -> Option < Out >
72
+ fn lookup < In , Out > (
73
+ & self ,
74
+ key : ( TypeId , u128 ) ,
75
+ input : & In ,
76
+ ) -> Option < & Constrained < In :: Constraint , Out > >
121
77
where
122
78
In : Input ,
123
79
Out : Clone + ' static ,
124
80
{
125
81
self . map
126
- . get_mut ( & key) ?
127
- . iter_mut ( )
82
+ . get ( & key) ?
83
+ . iter ( )
128
84
. find_map ( |entry| entry. lookup :: < In , Out > ( input) )
129
85
}
130
86
@@ -151,8 +107,6 @@ struct Entry {
151
107
///
152
108
/// This is of type `Constrained<In::Constraint, Out>`.
153
109
constrained : Box < dyn Any > ,
154
- /// How many evictions have passed since the entry has been last used.
155
- age : u32 ,
156
110
}
157
111
158
112
/// A value with a constraint.
@@ -172,22 +126,18 @@ impl Entry {
172
126
{
173
127
Self {
174
128
constrained : Box :: new ( Constrained { constraint, output } ) ,
175
- age : 0 ,
176
129
}
177
130
}
178
131
179
132
/// Return the entry's output if it is valid for the given input.
180
- fn lookup < In , Out > ( & mut self , input : & In ) -> Option < Out >
133
+ fn lookup < In , Out > ( & self , input : & In ) -> Option < & Constrained < In :: Constraint , Out > >
181
134
where
182
135
In : Input ,
183
136
Out : Clone + ' static ,
184
137
{
185
- let Constrained :: < In :: Constraint , Out > { constraint , output } =
138
+ let constrained : & Constrained < In :: Constraint , Out > =
186
139
self . constrained . downcast_ref ( ) . expect ( "wrong entry type" ) ;
187
140
188
- input. valid ( constraint) . then ( || {
189
- self . age = 0 ;
190
- output. clone ( )
191
- } )
141
+ input. valid ( & constrained. constraint ) . then ( || constrained)
192
142
}
193
143
}
0 commit comments