Traditionally the downside of thead-locals has been that usage is constrainted to the LocalKey::with closure with no lifetime escapement, the rationale being that anything beyond this is of an indeterminate lifetime. There is however a way around this limitation: by using a barrier to rendezvous worker threads during runtime shutdown, no tasks will outlive thread local data belonging to any worker thread, and all pointers to thread locals created within an async context and held therein will be of a valid lifetime. Utilizing this barrier mechanism, this crate introduces AsyncLocal::with_async, the async counterpart of LocalKey::with, as well as the unsafe pointer types and safety considerations foundational for using thread local data within an async context.
In order for async-local to protect thread local data within an async context, a barrier-protected Tokio Runtime must be used to ensure tasks never outlive thread local data owned by worker threads. By default, this crate makes no assumptions about the runtime used, and comes with the leaky-context
feature flag enabled which prevents Contextleaky-context
and configure the runtime using the tokio::main or tokio::test macro with the crate
attribute set to async_local
with only the barrier-protected-runtime
feature flag set on async-local
.
```rust
mod tests { use std::sync::atomic::{AtomicUsize, Ordering};
use async_local::{AsyncLocal, Context};
thread_local! {
static COUNTER: Context
#[tokio::test(crate = "asynclocal", flavor = "multithread")] async fn itincrements() { COUNTER .withasync(|counter| { Box::pin(async move { counter.fetch_add(1, Ordering::Release); }) }) .await; } } ```