Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add shared mutable state documentation #1759

Merged
merged 10 commits into from Feb 23, 2023
39 changes: 39 additions & 0 deletions axum/src/extract/state.rs
Expand Up @@ -295,6 +295,45 @@ use std::{
///
/// In general however we recommend you implement `Clone` for all your state types to avoid
/// potential type errors.
///
/// # When mutable shared state is needed
/// As state is used across routes it is not mutable by default. To mutate the state
/// you will need to use an `Arc<Mutex>` or similar.
/// You may have to use `tokio::sync::Mutex` instead of `std::sync::Mutex`,
/// since `std::sync::Mutex` cannot be used across `.await` points,
Vagelis-Prokopiou marked this conversation as resolved.
Show resolved Hide resolved
/// but this comes with performance cost.
/// See the
/// [tokio discussion on sync vs async mutex](https://docs.rs/tokio/1.25.0/tokio/sync/struct.Mutex.html#which-kind-of-mutex-should-you-use).
/// for a detailed comparison.
///
/// Be aware that many tasks that require an asynchronous mutex can lead to deadlocks
/// if steps are not taken to prevent a situation where
/// multiple tasks are waiting for each other to release the resource.
///
/// ```
/// use axum::extract::{State};
/// use axum::{Router, routing::get};
/// use std::ops::DerefMut;
///
/// struct AppState { data: String }
/// let state = AppState { data: "foo".to_string() };
/// let state = std::sync::Arc::new(tokio::sync::Mutex::new(state));
///
/// let app = Router::new()
/// .route("/", get(handler))
/// .with_state(state);
///
/// async fn handler(State(state): State<std::sync::Arc<tokio::sync::Mutex<AppState>>>) {
/// let mut guard = state.lock().await;
/// let state = guard.deref_mut();
/// state.data = "updated foo".to_string();
/// // ...
/// }
///
/// # let _: axum::Router = app;
/// ```


#[derive(Debug, Default, Clone, Copy)]
pub struct State<S>(pub S);

Expand Down