1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-28 01:32:57 +01:00

Allow to construct Data instances to avoid double Arc for Send + Sync types.

This commit is contained in:
Nikolay Kim 2019-04-29 09:26:12 -07:00
parent b51b5b763c
commit 29a841529f
4 changed files with 35 additions and 17 deletions

View File

@ -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

View File

@ -95,8 +95,8 @@ where
/// web::get().to(index)));
/// }
/// ```
pub fn data<S: 'static>(mut self, data: S) -> Self {
self.data.push(Box::new(Data::new(data)));
pub fn data<U: Into<Data<U>> + 'static>(mut self, data: U) -> Self {
self.data.push(Box::new(data.into()));
self
}

View File

@ -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<T>` 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<usize>,
/// counter: usize,
/// }
///
/// /// Use `Data<T>` extractor to access data in handler.
/// fn index(data: web::Data<MyData>) {
/// data.counter.set(data.counter.get() + 1);
/// fn index(data: web::Data<Mutex<MyData>>) {
/// 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<T>(Arc<T>);
impl<T> Data<T> {
pub(crate) fn new(state: T) -> Data<T> {
/// 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<T> {
Data(Arc::new(state))
}
@ -89,6 +98,12 @@ impl<T> Clone for Data<T> {
}
}
impl<T> From<T> for Data<T> {
fn from(data: T) -> Self {
Data::new(data)
}
}
impl<T: 'static> FromRequest for Data<T> {
type Config = ();
type Error = Error;

View File

@ -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!"));
}