From 7e09a19e7d3193d036a26ea6c3a6aa478488c248 Mon Sep 17 00:00:00 2001 From: Lewin Bormann Date: Fri, 21 Oct 2022 19:05:50 +0200 Subject: [PATCH] Add functionality for flushing the entire memoization cache (#16) --- README.md | 5 +++++ examples/full_featured.rs | 13 +++++++++---- examples/trivial.rs | 1 + inner/src/lib.rs | 12 +++++++++++- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c7cec9f..67c81d5 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,11 @@ to live: The cached value will never be older than duration provided and instead recalculated on the next request. +### Flushing + +If you memoize a function `f`, there will be a function called +`memoized_flush_f()` that allows you to clear the memoization cache. + ## Contributions ...are always welcome! This being my first procedural-macros crate, I am diff --git a/examples/full_featured.rs b/examples/full_featured.rs index 81070dd..1dc5b3e 100644 --- a/examples/full_featured.rs +++ b/examples/full_featured.rs @@ -2,6 +2,7 @@ use memoize::memoize; use std::thread; use std::time::{Duration, Instant}; +#[allow(dead_code)] #[derive(Debug, Clone)] struct ComplexStruct { s: String, @@ -25,12 +26,16 @@ fn main() { { println!("result: {:?}", hello("ABC".to_string())); println!("result: {:?}", hello("DEF".to_string())); - println!("result: {:?}", hello("ABC".to_string())); //Same as first + println!("result: {:?}", hello("ABC".to_string())); // Same as first thread::sleep(core::time::Duration::from_millis(2100)); + println!("result: {:?}", hello("ABC".to_string())); + println!("result: {:?}", hello("DEF".to_string())); + println!("result: {:?}", hello("ABC".to_string())); // Same as first + memoized_flush_hello(); println!("result: {:?}", hello("EFG".to_string())); - println!("result: {:?}", hello("ABC".to_string())); //Refreshed - println!("result: {:?}", hello("EFG".to_string())); //Same as first - println!("result: {:?}", hello("ABC".to_string())); //Same as refreshed + println!("result: {:?}", hello("ABC".to_string())); // Refreshed + println!("result: {:?}", hello("EFG".to_string())); // Same as first + println!("result: {:?}", hello("ABC".to_string())); // Same as refreshed println!("result: {:?}", memoized_original_hello("ABC".to_string())); } } diff --git a/examples/trivial.rs b/examples/trivial.rs index 630affe..7ee1e05 100644 --- a/examples/trivial.rs +++ b/examples/trivial.rs @@ -12,4 +12,5 @@ fn main() { assert!(!hello("World".to_string(), 0)); // Sometimes one might need the original function. assert!(!memoized_original_hello("World".to_string(), 0)); + memoized_flush_hello(); } diff --git a/inner/src/lib.rs b/inner/src/lib.rs index 576bc88..838883a 100644 --- a/inner/src/lib.rs +++ b/inner/src/lib.rs @@ -198,6 +198,9 @@ mod store { * * This mechanism can, in principle, be extended (in the source code) to any other cache mechanism. * + * `memoized_flush_()` allows you to clear the underlying memoization cache of a + * function. This function is generated with the same visibility as the memoized function. + * */ #[proc_macro_attribute] pub fn memoize(attr: TokenStream, item: TokenStream) -> TokenStream { @@ -206,6 +209,7 @@ pub fn memoize(attr: TokenStream, item: TokenStream) -> TokenStream { let fn_name = &sig.ident.to_string(); let renamed_name = format!("memoized_original_{}", fn_name); + let flush_name = syn::Ident::new(format!("memoized_flush_{}", fn_name).as_str(), sig.span()); let map_name = format!("memoized_mapping_{}", fn_name); // Extracted from the function signature. @@ -313,9 +317,15 @@ pub fn memoize(attr: TokenStream, item: TokenStream) -> TokenStream { let vis = &func.vis; + let flusher = quote::quote! { + #vis fn #flush_name() { + #store_ident.with(|hm| hm.borrow_mut().clear()); + } + }; + quote::quote! { #renamed_fn - + #flusher #store #[allow(unused_variables)]