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:
parent
a808293221
commit
1069dfa177
@ -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" >}}
|
||||
|
||||
Although this handler will work, `self.0` will be different depending on the number of threads and
|
||||
number of requests processed per thread. A proper implementation would use `web::Data` and `AtomicUsize`.
|
||||
Although this handler will work, `data.count` will only count the number of requests
|
||||
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" >}}
|
||||
|
||||
> **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
|
||||
> handles requests asynchronously. By blocking thread execution, all concurrent
|
||||
> 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
|
||||
[payloadexample]: https://docs.rs/actix-web/3/actix_web/web/struct.Payload.html
|
||||
[actix]: https://actix.github.io/actix/actix/
|
||||
[atomics]: https://doc.rust-lang.org/std/sync/atomic/
|
||||
[shared_mutable_state]: ../application#shared-mutable-state
|
||||
|
@ -1,29 +1,43 @@
|
||||
// <arc>
|
||||
use actix_web::{get, web, App, HttpServer, Responder};
|
||||
use std::cell::Cell;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct AppState {
|
||||
count: Arc<AtomicUsize>,
|
||||
local_count: Cell<usize>,
|
||||
global_count: Arc<AtomicUsize>,
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
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")]
|
||||
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]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
let data = AppState {
|
||||
count: Arc::new(AtomicUsize::new(0)),
|
||||
local_count: Cell::new(0),
|
||||
global_count: Arc::new(AtomicUsize::new(0)),
|
||||
};
|
||||
|
||||
HttpServer::new(move || {
|
||||
|
@ -5,7 +5,7 @@ use std::cell::Cell;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct AppState {
|
||||
count: Cell<i32>,
|
||||
count: Cell<usize>,
|
||||
}
|
||||
|
||||
async fn show_count(data: web::Data<AppState>) -> impl Responder {
|
||||
|
Loading…
x
Reference in New Issue
Block a user