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

remove unneeded UnsafeCell

This commit is contained in:
Nikolay Kim 2018-06-21 23:21:28 +06:00
parent 65ca563579
commit c9069e9a3c
4 changed files with 33 additions and 78 deletions

View File

@ -1,4 +1,3 @@
use std::cell::UnsafeCell;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::rc::Rc; use std::rc::Rc;
@ -297,12 +296,12 @@ impl<S: 'static> Route<S> {
/// `RouteHandler` wrapper. This struct is required because it needs to be /// `RouteHandler` wrapper. This struct is required because it needs to be
/// shared for resource level middlewares. /// shared for resource level middlewares.
struct InnerHandler<S>(Rc<UnsafeCell<Box<RouteHandler<S>>>>); struct InnerHandler<S>(Rc<Box<RouteHandler<S>>>);
impl<S: 'static> InnerHandler<S> { impl<S: 'static> InnerHandler<S> {
#[inline] #[inline]
fn new<H: Handler<S>>(h: H) -> Self { fn new<H: Handler<S>>(h: H) -> Self {
InnerHandler(Rc::new(UnsafeCell::new(Box::new(WrapHandler::new(h))))) InnerHandler(Rc::new(Box::new(WrapHandler::new(h))))
} }
#[inline] #[inline]
@ -313,14 +312,12 @@ impl<S: 'static> InnerHandler<S> {
R: Responder + 'static, R: Responder + 'static,
E: Into<Error> + 'static, E: Into<Error> + 'static,
{ {
InnerHandler(Rc::new(UnsafeCell::new(Box::new(AsyncHandler::new(h))))) InnerHandler(Rc::new(Box::new(AsyncHandler::new(h))))
} }
#[inline] #[inline]
pub fn handle(&self, req: HttpRequest<S>) -> AsyncResult<HttpResponse> { pub fn handle(&self, req: HttpRequest<S>) -> AsyncResult<HttpResponse> {
// reason: handler is unique per thread, handler get called from sync code only self.0.handle(req)
let h = unsafe { &mut *self.0.as_ref().get() };
h.handle(req)
} }
} }

View File

@ -1,4 +1,3 @@
use std::cell::UnsafeCell;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
use std::rc::Rc; use std::rc::Rc;
@ -19,7 +18,7 @@ use resource::ResourceHandler;
use router::Resource; use router::Resource;
type ScopeResource<S> = Rc<ResourceHandler<S>>; type ScopeResource<S> = Rc<ResourceHandler<S>>;
type Route<S> = UnsafeCell<Box<RouteHandler<S>>>; type Route<S> = Box<RouteHandler<S>>;
type ScopeResources<S> = Rc<Vec<(Resource, ScopeResource<S>)>>; type ScopeResources<S> = Rc<Vec<(Resource, ScopeResource<S>)>>;
type NestedInfo<S> = (Resource, Route<S>, Vec<Box<Predicate<S>>>); type NestedInfo<S> = (Resource, Route<S>, Vec<Box<Predicate<S>>>);
@ -145,7 +144,7 @@ impl<S: 'static> Scope<S> {
state: Rc::clone(&state), state: Rc::clone(&state),
filters: scope.take_filters(), filters: scope.take_filters(),
})]; })];
let handler = UnsafeCell::new(Box::new(Wrapper { scope, state })); let handler = Box::new(Wrapper { scope, state });
self.nested self.nested
.push((Resource::prefix("", &path), handler, filters)); .push((Resource::prefix("", &path), handler, filters));
@ -184,11 +183,8 @@ impl<S: 'static> Scope<S> {
let mut scope = f(scope); let mut scope = f(scope);
let filters = scope.take_filters(); let filters = scope.take_filters();
self.nested.push(( self.nested
Resource::prefix("", &path), .push((Resource::prefix("", &path), Box::new(scope), filters));
UnsafeCell::new(Box::new(scope)),
filters,
));
self self
} }
@ -384,10 +380,7 @@ impl<S: 'static> RouteHandler<S> for Scope<S> {
req.set_prefix_len(prefix_len); req.set_prefix_len(prefix_len);
req.match_info_mut().set_tail(prefix_len); req.match_info_mut().set_tail(prefix_len);
req.match_info_mut().set_url(url); req.match_info_mut().set_url(url);
return handler.handle(req);
let hnd: &mut RouteHandler<_> =
unsafe { (&mut *(handler.get())).as_mut() };
return hnd.handle(req);
} }
} }

View File

@ -394,11 +394,11 @@ impl<S: 'static> Iterator for TestApp<S> {
/// ///
/// fn main() { /// fn main() {
/// let resp = TestRequest::with_header("content-type", "text/plain") /// let resp = TestRequest::with_header("content-type", "text/plain")
/// .run(index) /// .run(&index)
/// .unwrap(); /// .unwrap();
/// assert_eq!(resp.status(), StatusCode::OK); /// assert_eq!(resp.status(), StatusCode::OK);
/// ///
/// let resp = TestRequest::default().run(index).unwrap(); /// let resp = TestRequest::default().run(&index).unwrap();
/// assert_eq!(resp.status(), StatusCode::BAD_REQUEST); /// assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
/// } /// }
/// ``` /// ```

View File

@ -1,5 +1,4 @@
use futures::{Async, Future, Poll}; use futures::{Async, Future, Poll};
use std::cell::UnsafeCell;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::rc::Rc; use std::rc::Rc;
@ -14,18 +13,8 @@ where
T: FromRequest<S>, T: FromRequest<S>,
S: 'static, S: 'static,
{ {
hnd: Rc<WithHnd<T, S, F, R>>, hnd: Rc<F>,
cfg: Rc<T::Config>, cfg: Rc<T::Config>,
}
pub struct WithHnd<T, S, F, R>
where
F: Fn(T) -> R,
T: FromRequest<S>,
S: 'static,
{
hnd: Rc<UnsafeCell<F>>,
_t: PhantomData<T>,
_s: PhantomData<S>, _s: PhantomData<S>,
} }
@ -38,11 +27,8 @@ where
pub fn new(f: F, cfg: T::Config) -> Self { pub fn new(f: F, cfg: T::Config) -> Self {
With { With {
cfg: Rc::new(cfg), cfg: Rc::new(cfg),
hnd: Rc::new(WithHnd { hnd: Rc::new(f),
hnd: Rc::new(UnsafeCell::new(f)),
_t: PhantomData,
_s: PhantomData, _s: PhantomData,
}),
} }
} }
} }
@ -82,7 +68,7 @@ where
S: 'static, S: 'static,
{ {
started: bool, started: bool,
hnd: Rc<WithHnd<T, S, F, R>>, hnd: Rc<F>,
cfg: Rc<T::Config>, cfg: Rc<T::Config>,
req: HttpRequest<S>, req: HttpRequest<S>,
fut1: Option<Box<Future<Item = T, Error = Error>>>, fut1: Option<Box<Future<Item = T, Error = Error>>>,
@ -122,29 +108,20 @@ where
} }
}; };
let fut = { let item = match (*self.hnd)(item).respond_to(&self.req) {
// clone handler, inicrease ref counter
let h = self.hnd.as_ref().hnd.clone();
// Enforce invariants before entering unsafe code.
// Only two references could exists With struct owns one, and line above
if Rc::weak_count(&h) != 0 || Rc::strong_count(&h) != 2 {
panic!("Multiple copies of handler are in use")
}
let hnd: &mut F = unsafe { &mut *h.as_ref().get() };
let item = match (*hnd)(item).respond_to(&self.req) {
Ok(item) => item.into(), Ok(item) => item.into(),
Err(e) => return Err(e.into()), Err(e) => return Err(e.into()),
}; };
match item.into() { match item.into() {
AsyncResultItem::Err(err) => return Err(err), AsyncResultItem::Err(err) => Err(err),
AsyncResultItem::Ok(resp) => return Ok(Async::Ready(resp)), AsyncResultItem::Ok(resp) => Ok(Async::Ready(resp)),
AsyncResultItem::Future(fut) => fut, AsyncResultItem::Future(fut) => {
}
};
self.fut2 = Some(fut); self.fut2 = Some(fut);
self.poll() self.poll()
} }
}
}
} }
pub(crate) struct WithAsync<T, S, F, R, I, E> pub(crate) struct WithAsync<T, S, F, R, I, E>
@ -156,8 +133,9 @@ where
T: FromRequest<S>, T: FromRequest<S>,
S: 'static, S: 'static,
{ {
hnd: Rc<WithHnd<T, S, F, R>>, hnd: Rc<F>,
cfg: Rc<T::Config>, cfg: Rc<T::Config>,
_s: PhantomData<S>,
} }
impl<T, S, F, R, I, E> WithAsync<T, S, F, R, I, E> impl<T, S, F, R, I, E> WithAsync<T, S, F, R, I, E>
@ -172,11 +150,8 @@ where
pub fn new(f: F, cfg: T::Config) -> Self { pub fn new(f: F, cfg: T::Config) -> Self {
WithAsync { WithAsync {
cfg: Rc::new(cfg), cfg: Rc::new(cfg),
hnd: Rc::new(WithHnd { hnd: Rc::new(f),
hnd: Rc::new(UnsafeCell::new(f)),
_s: PhantomData, _s: PhantomData,
_t: PhantomData,
}),
} }
} }
} }
@ -221,7 +196,7 @@ where
S: 'static, S: 'static,
{ {
started: bool, started: bool,
hnd: Rc<WithHnd<T, S, F, R>>, hnd: Rc<F>,
cfg: Rc<T::Config>, cfg: Rc<T::Config>,
req: HttpRequest<S>, req: HttpRequest<S>,
fut1: Option<Box<Future<Item = T, Error = Error>>>, fut1: Option<Box<Future<Item = T, Error = Error>>>,
@ -282,17 +257,7 @@ where
} }
}; };
self.fut2 = { self.fut2 = Some((*self.hnd)(item));
// clone handler, inicrease ref counter
let h = self.hnd.as_ref().hnd.clone();
// Enforce invariants before entering unsafe code.
// Only two references could exists With struct owns one, and line above
if Rc::weak_count(&h) != 0 || Rc::strong_count(&h) != 2 {
panic!("Multiple copies of handler are in use")
}
let hnd: &mut F = unsafe { &mut *h.as_ref().get() };
Some((*hnd)(item))
};
self.poll() self.poll()
} }
} }