Mercurial > lbo > hg > memoize
changeset 27:36657c45bae5
Added SecondsToLive parameter
author | Илья Ефимов <inferrna@gmail.com> |
---|---|
date | Thu, 10 Dec 2020 00:57:33 +0800 |
parents | 9bcf7bab10a4 |
children | 5689f7161462 |
files | examples/test1.rs src/lib.rs |
diffstat | 2 files changed, 63 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/test1.rs Fri Oct 16 10:32:22 2020 +0200 +++ b/examples/test1.rs Thu Dec 10 00:57:33 2020 +0800 @@ -1,25 +1,29 @@ use memoize::memoize; +use std::time::{Instant, Duration}; +use std::thread; #[derive(Debug, Clone)] struct ComplexStruct { s: String, b: bool, - i: i32, + i: Instant, } -#[memoize(Capacity: 123)] +#[memoize(Capacity: 123, SecondsToLive: 1)] fn hello(key: String) -> ComplexStruct { println!("hello: {}", key); ComplexStruct { s: key, b: false, - i: 332, + i: Instant::now(), } } fn main() { println!("result: {:?}", hello("ABC".to_string())); println!("result: {:?}", hello("DEF".to_string())); - println!("result: {:?}", hello("ABC".to_string())); + println!("result: {:?}", hello("ABC".to_string())); //Same as first + thread::sleep(Duration::from_millis(2100)); + println!("result: {:?}", hello("ABC".to_string())); //Refreshed println!("result: {:?}", memoized_original_hello("ABC".to_string())); }
--- a/src/lib.rs Fri Oct 16 10:32:22 2020 +0200 +++ b/src/lib.rs Thu Dec 10 00:57:33 2020 +0800 @@ -49,16 +49,19 @@ use syn::parse as p; #[derive(Default, Debug, Clone)] - struct CacheOptions { + pub(crate) struct CacheOptions { lru_max_entries: Option<usize>, + pub(crate) seconds_to_live: Option<u64>, } #[derive(Debug, Clone)] enum CacheOption { LRUMaxEntries(usize), + SecondsToLive(u64), } syn::custom_keyword!(Capacity); + syn::custom_keyword!(SecondsToLive); syn::custom_punctuation!(Colon, :); // To extend option parsing, add functionality here. @@ -72,6 +75,13 @@ return Ok(CacheOption::LRUMaxEntries(cap.base10_parse()?)); } + if la.peek(SecondsToLive) { + let _: SecondsToLive = input.parse().unwrap(); + let _: Colon = input.parse().unwrap(); + let cap: syn::LitInt = input.parse().unwrap(); + + return Ok(CacheOption::SecondsToLive(cap.base10_parse()?)); + } Err(la.error()) } } @@ -85,6 +95,7 @@ for opt in f { match opt { CacheOption::LRUMaxEntries(cap) => opts.lru_max_entries = Some(cap), + CacheOption::SecondsToLive(sec) => opts.seconds_to_live = Some(sec), } } Ok(opts) @@ -103,6 +114,10 @@ ) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) { let options: CacheOptions = syn::parse(attr.clone()).unwrap(); + let value_type = match options.seconds_to_live { + None => quote::quote! {#value_type}, + Some(_) => quote::quote! {(std::time::Instant, #value_type)}, + }; // This is the unbounded default. match options.lru_max_entries { None => ( @@ -219,17 +234,48 @@ let syntax_names_tuple = quote::quote! { (#(#input_names),*) }; let syntax_names_tuple_cloned = quote::quote! { (#(#input_names.clone()),*) }; let (insert_fn, get_fn) = store::cache_access_methods(&attr); - let memoizer = quote::quote! { - #sig { - let mut hm = &mut #store_ident.lock().unwrap(); - if let Some(r) = hm.#get_fn(&#syntax_names_tuple_cloned) { - return r.clone(); + #[cfg(feature = "full")] + let memoizer = { + let options: store::CacheOptions = syn::parse(attr.clone()).unwrap(); + match options.seconds_to_live { + None => quote::quote! { + #sig { + let mut hm = &mut #store_ident.lock().unwrap(); + if let Some(r) = hm.#get_fn(&#syntax_names_tuple_cloned) { + return r.clone(); + } + let r = #memoized_id(#(#input_names.clone()),*); + hm.#insert_fn(#syntax_names_tuple, r.clone()); + r + } + }, + Some(ttl) => quote::quote! { + #sig { + let mut hm = &mut #store_ident.lock().unwrap(); + if let Some((last_updated, r)) = hm.#get_fn(&#syntax_names_tuple_cloned) { + if last_updated.elapsed().as_secs() < #ttl { + return r.clone(); + } + } + let r = #memoized_id(#(#input_names.clone()),*); + hm.#insert_fn(#syntax_names_tuple, (std::time::Instant::now(), r.clone())); + r + } } - let r = #memoized_id(#(#input_names.clone()),*); - hm.#insert_fn(#syntax_names_tuple, r.clone()); - r } }; + #[cfg(not(feature = "full"))] + let memoizer = quote::quote! { + #sig { + let mut hm = &mut #store_ident.lock().unwrap(); + if let Some(r) = hm.#get_fn(&#syntax_names_tuple_cloned) { + return r.clone(); + } + let r = #memoized_id(#(#input_names.clone()),*); + hm.#insert_fn(#syntax_names_tuple, r.clone()); + r + } + }; (quote::quote! { #store