@@ -14,52 +14,6 @@ thread_local! {
1414 static CACHE : RefCell <Cache > = RefCell :: new( Cache :: default ( ) ) ;
1515}
1616
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-
6317/// Execute a function or use a cached result for it.
6418pub fn memoized < In , Out , F > ( id : TypeId , input : In , func : F ) -> Out
6519where
@@ -76,55 +30,57 @@ where
7630 ( id, hash)
7731 } ;
7832
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-
8833 // Point all tracked parts of the input to these constraints.
8934 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+ }
9143
9244 // 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) ;
9447
95- // Add the new constraints to the previous outer ones.
48+ // Add the new constraints to the outer ones.
9649 outer. join ( & constraint) ;
9750
9851 // 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 ( ) ) ;
10253
10354 output
10455 } )
10556}
10657
58+ /// Completely clear the cache.
59+ pub fn clear ( ) {
60+ CACHE . with ( |cache| cache. borrow_mut ( ) . map . clear ( ) ) ;
61+ }
62+
10763/// The global cache.
10864#[ derive( Default ) ]
10965struct Cache {
11066 /// Maps from function IDs + hashes to memoized results.
11167 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 ,
11668}
11769
11870impl Cache {
11971 /// 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 > >
12177 where
12278 In : Input ,
12379 Out : Clone + ' static ,
12480 {
12581 self . map
126- . get_mut ( & key) ?
127- . iter_mut ( )
82+ . get ( & key) ?
83+ . iter ( )
12884 . find_map ( |entry| entry. lookup :: < In , Out > ( input) )
12985 }
13086
@@ -151,8 +107,6 @@ struct Entry {
151107 ///
152108 /// This is of type `Constrained<In::Constraint, Out>`.
153109 constrained : Box < dyn Any > ,
154- /// How many evictions have passed since the entry has been last used.
155- age : u32 ,
156110}
157111
158112/// A value with a constraint.
@@ -172,22 +126,18 @@ impl Entry {
172126 {
173127 Self {
174128 constrained : Box :: new ( Constrained { constraint, output } ) ,
175- age : 0 ,
176129 }
177130 }
178131
179132 /// 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 > >
181134 where
182135 In : Input ,
183136 Out : Clone + ' static ,
184137 {
185- let Constrained :: < In :: Constraint , Out > { constraint , output } =
138+ let constrained : & Constrained < In :: Constraint , Out > =
186139 self . constrained . downcast_ref ( ) . expect ( "wrong entry type" ) ;
187140
188- input. valid ( constraint) . then ( || {
189- self . age = 0 ;
190- output. clone ( )
191- } )
141+ input. valid ( & constrained. constraint ) . then ( || constrained)
192142 }
193143}
0 commit comments