Skip to content

Commit

Permalink
fix once async sync_writes deadlock
Browse files Browse the repository at this point in the history
  • Loading branch information
Lesny committed Oct 31, 2023
1 parent b101556 commit 7ec891b
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
6 changes: 3 additions & 3 deletions cached_proc_macro/src/once.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ pub fn once(args: TokenStream, input: TokenStream) -> TokenStream {
#set_cache_and_return
};

let return_cache_block = quote! {
let r_lock_return_cache_block = quote! {
{
#r_lock
if let Some(result) = &*cached {
Expand All @@ -216,7 +216,7 @@ pub fn once(args: TokenStream, input: TokenStream) -> TokenStream {

let do_set_return_block = if args.sync_writes {
quote! {
#return_cache_block
#r_lock_return_cache_block
#w_lock
if let Some(result) = &*cached {
#return_cache_block
Expand All @@ -226,7 +226,7 @@ pub fn once(args: TokenStream, input: TokenStream) -> TokenStream {
}
} else {
quote! {
#return_cache_block
#r_lock_return_cache_block
#function_call
#w_lock
#set_cache_and_return
Expand Down
27 changes: 27 additions & 0 deletions tests/cached.rs
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,33 @@ async fn test_cached_sync_writes_a() {
assert_eq!(a, c.await.unwrap());
}

#[cfg(feature = "async")]
#[once(sync_writes = true)]
async fn once_sync_writes_a(s: &tokio::sync::Mutex<String>) -> String {
let mut guard = s.lock().await;
let results: String = (*guard).clone().to_string();
*guard = "consumed".to_string();
results.to_string()
}

#[cfg(feature = "async")]
#[tokio::test]
async fn test_once_sync_writes_a() {
let a_mutex = tokio::sync::Mutex::new("a".to_string());
let b_mutex = tokio::sync::Mutex::new("b".to_string());
let fut_a = once_sync_writes_a(&a_mutex);
let fut_b = once_sync_writes_a(&b_mutex);
let a = fut_a.await;
let b = fut_b.await;
assert_eq!(a, b);
assert_eq!("a", a);

//check if cache function is executed for a
assert_eq!("consumed", a_mutex.lock().await.to_string());
//check if cache inner is not executed for b (not executed second time)
assert_eq!("b", b_mutex.lock().await.to_string());
}

#[cached(size = 2)]
fn cached_smartstring(s: smartstring::alias::String) -> smartstring::alias::String {
if s == "very stringy" {
Expand Down

0 comments on commit 7ec891b

Please sign in to comment.