1
0
mirror of https://github.com/fafhrd91/actix-net synced 2024-11-27 18:02:58 +01:00

add custom cell

This commit is contained in:
Nikolay Kim 2018-10-02 22:18:07 -07:00
parent 79b525bc2f
commit 20b03a4780
7 changed files with 87 additions and 35 deletions

View File

@ -36,6 +36,8 @@ ssl = ["openssl", "tokio-openssl"]
# rustls # rustls
rust-tls = ["rustls", "tokio-rustls", "webpki", "webpki-roots"] rust-tls = ["rustls", "tokio-rustls", "webpki", "webpki-roots"]
cell = []
[dependencies] [dependencies]
actix = "0.7.0" actix = "0.7.0"

62
src/cell.rs Normal file
View File

@ -0,0 +1,62 @@
//! Custom cell impl
#[cfg(feature = "cell")]
use std::cell::UnsafeCell;
#[cfg(not(feature = "cell"))]
use std::cell::{Ref, RefCell, RefMut};
use std::fmt;
use std::rc::Rc;
pub(crate) struct Cell<T> {
#[cfg(feature = "cell")]
inner: Rc<UnsafeCell<T>>,
#[cfg(not(feature = "cell"))]
inner: Rc<RefCell<T>>,
}
impl<T> Clone for Cell<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<T: fmt::Debug> fmt::Debug for Cell<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.inner.fmt(f)
}
}
#[cfg(feature = "cell")]
impl<T> Cell<T> {
pub(crate) fn new(inner: T) -> Self {
Self {
inner: Rc::new(UnsafeCell::new(inner)),
}
}
pub(crate) fn borrow(&self) -> &T {
unsafe { &*self.inner.as_ref().get() }
}
pub(crate) fn borrow_mut(&self) -> &mut T {
unsafe { &mut *self.inner.as_ref().get() }
}
}
#[cfg(not(feature = "cell"))]
impl<T> Cell<T> {
pub(crate) fn new(inner: T) -> Self {
Self {
inner: Rc::new(RefCell::new(inner)),
}
}
pub(crate) fn borrow(&self) -> Ref<T> {
self.inner.borrow()
}
pub(crate) fn borrow_mut(&self) -> RefMut<T> {
self.inner.borrow_mut()
}
}

View File

@ -1,19 +1,17 @@
use std::cell::RefCell;
use std::rc::Rc;
use futures::Poll; use futures::Poll;
use super::cell::Cell;
use super::service::Service; use super::service::Service;
/// Service that allows to turn non-clone service to a service with `Clone` impl /// Service that allows to turn non-clone service to a service with `Clone` impl
pub struct CloneableService<S: Service + 'static> { pub struct CloneableService<S: Service + 'static> {
service: Rc<RefCell<S>>, service: Cell<S>,
} }
impl<S: Service + 'static> CloneableService<S> { impl<S: Service + 'static> CloneableService<S> {
pub fn new(service: S) -> Self { pub fn new(service: S) -> Self {
Self { Self {
service: Rc::new(RefCell::new(service)), service: Cell::new(service),
} }
} }
} }

View File

@ -55,6 +55,7 @@ extern crate webpki;
#[cfg(feature = "rust-tls")] #[cfg(feature = "rust-tls")]
extern crate webpki_roots; extern crate webpki_roots;
mod cell;
pub mod cloneable; pub mod cloneable;
pub mod connector; pub mod connector;
pub mod counter; pub mod counter;

View File

@ -1,9 +1,7 @@
use std::cell::RefCell;
use std::rc::Rc;
use futures::{Async, Future, Poll}; use futures::{Async, Future, Poll};
use super::{IntoNewService, NewService, Service}; use super::{IntoNewService, NewService, Service};
use cell::Cell;
/// Service for the `and_then` combinator, chaining a computation onto the end /// Service for the `and_then` combinator, chaining a computation onto the end
/// of another service which completes successfully. /// of another service which completes successfully.
@ -11,7 +9,7 @@ use super::{IntoNewService, NewService, Service};
/// This is created by the `ServiceExt::and_then` method. /// This is created by the `ServiceExt::and_then` method.
pub struct AndThen<A, B> { pub struct AndThen<A, B> {
a: A, a: A,
b: Rc<RefCell<B>>, b: Cell<B>,
} }
impl<A, B> AndThen<A, B> impl<A, B> AndThen<A, B>
@ -21,10 +19,7 @@ where
{ {
/// Create new `AndThen` combinator /// Create new `AndThen` combinator
pub fn new(a: A, b: B) -> Self { pub fn new(a: A, b: B) -> Self {
Self { Self { a, b: Cell::new(b) }
a,
b: Rc::new(RefCell::new(b)),
}
} }
} }
@ -66,7 +61,7 @@ where
A: Service, A: Service,
B: Service<Request = A::Response, Error = A::Error>, B: Service<Request = A::Response, Error = A::Error>,
{ {
b: Rc<RefCell<B>>, b: Cell<B>,
fut_b: Option<B::Future>, fut_b: Option<B::Future>,
fut_a: A::Future, fut_a: A::Future,
} }
@ -76,7 +71,7 @@ where
A: Service, A: Service,
B: Service<Request = A::Response, Error = A::Error>, B: Service<Request = A::Response, Error = A::Error>,
{ {
fn new(fut_a: A::Future, b: Rc<RefCell<B>>) -> Self { fn new(fut_a: A::Future, b: Cell<B>) -> Self {
AndThenFuture { AndThenFuture {
b, b,
fut_a, fut_a,

View File

@ -1,9 +1,7 @@
use std::cell::RefCell;
use std::rc::Rc;
use futures::{Async, Future, Poll}; use futures::{Async, Future, Poll};
use super::{IntoNewService, NewService, Service}; use super::{IntoNewService, NewService, Service};
use cell::Cell;
/// Service for the `then` combinator, chaining a computation onto the end of /// Service for the `then` combinator, chaining a computation onto the end of
/// another service. /// another service.
@ -11,7 +9,7 @@ use super::{IntoNewService, NewService, Service};
/// This is created by the `ServiceExt::then` method. /// This is created by the `ServiceExt::then` method.
pub struct Then<A, B> { pub struct Then<A, B> {
a: A, a: A,
b: Rc<RefCell<B>>, b: Cell<B>,
} }
impl<A, B> Then<A, B> impl<A, B> Then<A, B>
@ -21,10 +19,7 @@ where
{ {
/// Create new `Then` combinator /// Create new `Then` combinator
pub fn new(a: A, b: B) -> Then<A, B> { pub fn new(a: A, b: B) -> Then<A, B> {
Then { Then { a, b: Cell::new(b) }
a,
b: Rc::new(RefCell::new(b)),
}
} }
} }
@ -66,7 +61,7 @@ where
A: Service, A: Service,
B: Service<Request = Result<A::Response, A::Error>>, B: Service<Request = Result<A::Response, A::Error>>,
{ {
b: Rc<RefCell<B>>, b: Cell<B>,
fut_b: Option<B::Future>, fut_b: Option<B::Future>,
fut_a: A::Future, fut_a: A::Future,
} }
@ -76,7 +71,7 @@ where
A: Service, A: Service,
B: Service<Request = Result<A::Response, A::Error>>, B: Service<Request = Result<A::Response, A::Error>>,
{ {
fn new(fut_a: A::Future, b: Rc<RefCell<B>>) -> Self { fn new(fut_a: A::Future, b: Cell<B>) -> Self {
ThenFuture { ThenFuture {
b, b,
fut_a, fut_a,
@ -243,6 +238,7 @@ mod tests {
use super::*; use super::*;
use service::{NewServiceExt, ServiceExt}; use service::{NewServiceExt, ServiceExt};
#[derive(Clone)]
struct Srv1(Rc<Cell<usize>>); struct Srv1(Rc<Cell<usize>>);
impl Service for Srv1 { impl Service for Srv1 {
type Request = Result<&'static str, &'static str>; type Request = Result<&'static str, &'static str>;
@ -263,7 +259,6 @@ mod tests {
} }
} }
#[derive(Clone)]
struct Srv2(Rc<Cell<usize>>); struct Srv2(Rc<Cell<usize>>);
impl Service for Srv2 { impl Service for Srv2 {
@ -298,7 +293,7 @@ mod tests {
#[test] #[test]
fn test_call() { fn test_call() {
let cnt = Rc::new(Cell::new(0)); let cnt = Rc::new(Cell::new(0));
let mut srv = Srv1(cnt.clone()).then(Srv2(cnt)); let mut srv = Srv1(cnt.clone()).then(Srv2(cnt)).clone();
let res = srv.call(Ok("srv1")).poll(); let res = srv.call(Ok("srv1")).poll();
assert!(res.is_ok()); assert!(res.is_ok());
@ -315,7 +310,7 @@ mod tests {
let cnt2 = cnt.clone(); let cnt2 = cnt.clone();
let blank = move || Ok::<_, ()>(Srv1(cnt2.clone())); let blank = move || Ok::<_, ()>(Srv1(cnt2.clone()));
let new_srv = blank.into_new_service().then(move || Ok(Srv2(cnt.clone()))); let new_srv = blank.into_new_service().then(move || Ok(Srv2(cnt.clone())));
if let Async::Ready(mut srv) = new_srv.new_service().poll().unwrap() { if let Async::Ready(mut srv) = new_srv.clone().new_service().poll().unwrap() {
let res = srv.call(Ok("srv1")).poll(); let res = srv.call(Ok("srv1")).poll();
assert!(res.is_ok()); assert!(res.is_ok());
assert_eq!(res.unwrap(), Async::Ready(("srv1", "ok"))); assert_eq!(res.unwrap(), Async::Ready(("srv1", "ok")));

View File

@ -1,5 +1,3 @@
use std::cell::RefCell;
use std::rc::Rc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use futures::future::{ok, FutureResult}; use futures::future::{ok, FutureResult};
@ -7,11 +5,12 @@ use futures::{Async, Future, Poll};
use tokio_current_thread::spawn; use tokio_current_thread::spawn;
use tokio_timer::sleep; use tokio_timer::sleep;
use super::cell::Cell;
use super::service::{NewService, Service}; use super::service::{NewService, Service};
use super::Never; use super::Never;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct LowResTimer(Rc<RefCell<Inner>>); pub struct LowResTimer(Cell<Inner>);
#[derive(Debug)] #[derive(Debug)]
struct Inner { struct Inner {
@ -30,7 +29,7 @@ impl Inner {
impl LowResTimer { impl LowResTimer {
pub fn with_interval(interval: Duration) -> LowResTimer { pub fn with_interval(interval: Duration) -> LowResTimer {
LowResTimer(Rc::new(RefCell::new(Inner::new(interval)))) LowResTimer(Cell::new(Inner::new(interval)))
} }
pub fn timer(&self) -> LowResTimerService { pub fn timer(&self) -> LowResTimerService {
@ -40,7 +39,7 @@ impl LowResTimer {
impl Default for LowResTimer { impl Default for LowResTimer {
fn default() -> Self { fn default() -> Self {
LowResTimer(Rc::new(RefCell::new(Inner::new(Duration::from_secs(1))))) LowResTimer(Cell::new(Inner::new(Duration::from_secs(1))))
} }
} }
@ -58,11 +57,11 @@ impl NewService for LowResTimer {
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct LowResTimerService(Rc<RefCell<Inner>>); pub struct LowResTimerService(Cell<Inner>);
impl LowResTimerService { impl LowResTimerService {
pub fn with_resolution(resolution: Duration) -> LowResTimerService { pub fn with_resolution(resolution: Duration) -> LowResTimerService {
LowResTimerService(Rc::new(RefCell::new(Inner::new(resolution)))) LowResTimerService(Cell::new(Inner::new(resolution)))
} }
/// Get current time. This function has to be called from /// Get current time. This function has to be called from