1
0
mirror of https://github.com/actix/actix-website synced 2025-01-22 16:15:56 +01:00

Clarify use of Arc in shared state (#221)

This commit is contained in:
Mark Lodato 2021-04-05 19:41:26 -04:00 committed by GitHub
parent a808293221
commit 1069dfa177
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 8 deletions

View File

@ -99,11 +99,15 @@ Here is an example of a handler that stores the number of processed requests:
{{< include-example example="request-handlers" file="main.rs" section="data" >}} {{< include-example example="request-handlers" file="main.rs" section="data" >}}
Although this handler will work, `self.0` will be different depending on the number of threads and Although this handler will work, `data.count` will only count the number of requests
number of requests processed per thread. A proper implementation would use `web::Data` and `AtomicUsize`. handled *by each thread*. To count the number of total requests across all threads,
one should use `Arc` and [atomics][atomics].
{{< include-example example="request-handlers" file="handlers_arc.rs" section="arc" >}} {{< include-example example="request-handlers" file="handlers_arc.rs" section="arc" >}}
> **Note**, if you want the *entire* state to be shared across all threads, use
> `web::Data` and `app_data` as described in [Shared Mutable State][shared_mutable_state].
> Be careful with synchronization primitives like `Mutex` or `RwLock`. The `actix-web` framework > Be careful with synchronization primitives like `Mutex` or `RwLock`. The `actix-web` framework
> handles requests asynchronously. By blocking thread execution, all concurrent > handles requests asynchronously. By blocking thread execution, all concurrent
> request handling processes would block. If you need to share or update some state > request handling processes would block. If you need to share or update some state
@ -119,3 +123,5 @@ number of requests processed per thread. A proper implementation would use `web:
[bytesexample]: https://docs.rs/actix-web/3/actix_web/trait.FromRequest.html#example-4 [bytesexample]: https://docs.rs/actix-web/3/actix_web/trait.FromRequest.html#example-4
[payloadexample]: https://docs.rs/actix-web/3/actix_web/web/struct.Payload.html [payloadexample]: https://docs.rs/actix-web/3/actix_web/web/struct.Payload.html
[actix]: https://actix.github.io/actix/actix/ [actix]: https://actix.github.io/actix/actix/
[atomics]: https://doc.rust-lang.org/std/sync/atomic/
[shared_mutable_state]: ../application#shared-mutable-state

View File

@ -1,29 +1,43 @@
// <arc> // <arc>
use actix_web::{get, web, App, HttpServer, Responder}; use actix_web::{get, web, App, HttpServer, Responder};
use std::cell::Cell;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc; use std::sync::Arc;
#[derive(Clone)] #[derive(Clone)]
struct AppState { struct AppState {
count: Arc<AtomicUsize>, local_count: Cell<usize>,
global_count: Arc<AtomicUsize>,
} }
#[get("/")] #[get("/")]
async fn show_count(data: web::Data<AppState>) -> impl Responder { async fn show_count(data: web::Data<AppState>) -> impl Responder {
format!("count: {}", data.count.load(Ordering::Relaxed)) format!(
"global_count: {}\nlocal_count: {}",
data.global_count.load(Ordering::Relaxed),
data.local_count.get()
)
} }
#[get("/add")] #[get("/add")]
async fn add_one(data: web::Data<AppState>) -> impl Responder { async fn add_one(data: web::Data<AppState>) -> impl Responder {
data.count.fetch_add(1, Ordering::Relaxed); data.global_count.fetch_add(1, Ordering::Relaxed);
format!("count: {}", data.count.load(Ordering::Relaxed)) let local_count = data.local_count.get();
data.local_count.set(local_count + 1);
format!(
"global_count: {}\nlocal_count: {}",
data.global_count.load(Ordering::Relaxed),
data.local_count.get()
)
} }
#[actix_web::main] #[actix_web::main]
async fn main() -> std::io::Result<()> { async fn main() -> std::io::Result<()> {
let data = AppState { let data = AppState {
count: Arc::new(AtomicUsize::new(0)), local_count: Cell::new(0),
global_count: Arc::new(AtomicUsize::new(0)),
}; };
HttpServer::new(move || { HttpServer::new(move || {

View File

@ -5,7 +5,7 @@ use std::cell::Cell;
#[derive(Clone)] #[derive(Clone)]
struct AppState { struct AppState {
count: Cell<i32>, count: Cell<usize>,
} }
async fn show_count(data: web::Data<AppState>) -> impl Responder { async fn show_count(data: web::Data<AppState>) -> impl Responder {