diff --git a/CHANGES.md b/CHANGES.md index 08a60d33f..53ff98cc4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,10 @@ # Changes +### Changed + +* Allow to construct `Data` instances to avoid double `Arc` for `Send + Sync` types. + + ## [1.0.0-beta.2] - 2019-04-24 ### Added diff --git a/src/app.rs b/src/app.rs index b478b6c07..0e306a00b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -95,8 +95,8 @@ where /// web::get().to(index))); /// } /// ``` - pub fn data(mut self, data: S) -> Self { - self.data.push(Box::new(Data::new(data))); + pub fn data> + 'static>(mut self, data: U) -> Self { + self.data.push(Box::new(data.into())); self } @@ -301,14 +301,14 @@ where /// lifecycle (request -> response), modifying request/response as /// necessary, across all requests managed by the *Application*. /// - /// Use middleware when you need to read or modify *every* request or + /// Use middleware when you need to read or modify *every* request or /// response in some way. /// - /// Notice that the keyword for registering middleware is `wrap`. As you + /// Notice that the keyword for registering middleware is `wrap`. As you /// register middleware using `wrap` in the App builder, imagine wrapping /// layers around an inner App. The first middleware layer exposed to a /// Request is the outermost layer-- the *last* registered in - /// the builder chain. Consequently, the *first* middleware registered + /// the builder chain. Consequently, the *first* middleware registered /// in the builder chain is the *last* to execute during request processing. /// /// ```rust diff --git a/src/data.rs b/src/data.rs index 0c896fcc2..c77ba3e22 100644 --- a/src/data.rs +++ b/src/data.rs @@ -33,29 +33,33 @@ pub(crate) trait DataFactoryResult { /// instance for each thread, thus application data must be constructed /// multiple times. If you want to share data between different /// threads, a shareable object should be used, e.g. `Send + Sync`. Application -/// data does not need to be `Send` or `Sync`. Internally `Data` instance -/// uses `Arc`. +/// data does not need to be `Send` or `Sync`. Internally `Data` type +/// uses `Arc`. if your data implements `Send` + `Sync` traits you can +/// use `web::Data::new()` and avoid double `Arc`. /// /// If route data is not set for a handler, using `Data` extractor would /// cause *Internal Server Error* response. /// /// ```rust -/// use std::cell::Cell; +/// use std::sync::Mutex; /// use actix_web::{web, App}; /// /// struct MyData { -/// counter: Cell, +/// counter: usize, /// } /// /// /// Use `Data` extractor to access data in handler. -/// fn index(data: web::Data) { -/// data.counter.set(data.counter.get() + 1); +/// fn index(data: web::Data>) { +/// let mut data = data.lock().unwrap(); +/// data.counter += 1; /// } /// /// fn main() { +/// let data = web::Data::new(Mutex::new(MyData{ counter: 0 })); +/// /// let app = App::new() /// // Store `MyData` in application storage. -/// .data(MyData{ counter: Cell::new(0) }) +/// .data(data.clone()) /// .service( /// web::resource("/index.html").route( /// web::get().to(index))); @@ -65,7 +69,12 @@ pub(crate) trait DataFactoryResult { pub struct Data(Arc); impl Data { - pub(crate) fn new(state: T) -> Data { + /// Create new `Data` instance. + /// + /// Internally `Data` type uses `Arc`. if your data implements + /// `Send` + `Sync` traits you can use `web::Data::new()` and + /// avoid double `Arc`. + pub fn new(state: T) -> Data { Data(Arc::new(state)) } @@ -89,6 +98,12 @@ impl Clone for Data { } } +impl From for Data { + fn from(data: T) -> Self { + Data::new(data) + } +} + impl FromRequest for Data { type Config = (); type Error = Error; diff --git a/src/test.rs b/src/test.rs index 6bdc3ce3c..dc55df639 100644 --- a/src/test.rs +++ b/src/test.rs @@ -555,7 +555,7 @@ mod tests { web::resource("/index.html") .route(web::put().to(|| HttpResponse::Ok().body("put!"))) .route(web::patch().to(|| HttpResponse::Ok().body("patch!"))) - .route(web::delete().to(|| HttpResponse::Ok().body("delete!"))) + .route(web::delete().to(|| HttpResponse::Ok().body("delete!"))), ), ); @@ -575,9 +575,7 @@ mod tests { let result = read_response(&mut app, patch_req); assert_eq!(result, Bytes::from_static(b"patch!")); - let delete_req = TestRequest::delete() - .uri("/index.html") - .to_request(); + let delete_req = TestRequest::delete().uri("/index.html").to_request(); let result = read_response(&mut app, delete_req); assert_eq!(result, Bytes::from_static(b"delete!")); }