stretto
stretto copied to clipboard
Possible deadlock in `wait` in `async_std` runtime
Code below may freeze on wait()
call. It happens most of the time for me (macOS).
use async_std::task;
use stretto::AsyncCache;
fn main() {
let max_cost = 10_000;
let lru = AsyncCache::new(max_cost * 10, max_cost as i64, task::spawn)
.expect("failed to create cache");
task::block_on(task::spawn(async move {
for i in 0..10_000 {
println!("i = {i}, len before insert = {}", lru.len());
let value = 123;
let cost = 1;
lru.insert(i, value, cost).await;
lru.wait().await.unwrap(); // <-- freezes here
}
println!("done");
}));
}
I also have a question. Is there an easy way to predict how many items a cache will fit (with parameters above) if we always use cost = 1? Seems like it's capping out at ~175 items in an example above (max_cost = 10_000, with each item cost = 1).
Hi, the freeze situation happens on async-std runtime. I will add some test cases for async-std and try to fix it.
There is an ignore_internal_cost
configuration, when you build cache you can set it to true
, If you want to store the exact max_cost
items to the cache, you should build cache like this.
use async_std::task;
use stretto::AsyncCache;
fn main() {
let max_cost = 10_000;
let lru = AsyncCacheBuilder::new(max_cost * 10, max_cost as i64)
.set_ignore_internal_cost(true)
.finalize(tokio::spawn)
.expect("failed to create cache");
// your code here
}
Maybe it is caused by blow code:
let waker;
cfg_std_expr!(
waker = self.inner.waker.lock().unwrap().take();
);
cfg_not_std_expr!(
waker = self.inner.waker.lock().take();
);
if let Some(waker) = waker {
waker.wake();
}
Some(0)
} else if val == 0 {
None
} else {
Some(val - 1)
the task has been woken and polled before updating count
. So we should update count firstly and then wake up the Future
.
I have created a PR in wg repository.