1
0
mirror of https://github.com/fafhrd91/actix-net synced 2024-11-24 00:01:11 +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
rust-tls = ["rustls", "tokio-rustls", "webpki", "webpki-roots"]
cell = []
[dependencies]
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 super::cell::Cell;
use super::service::Service;
/// Service that allows to turn non-clone service to a service with `Clone` impl
pub struct CloneableService<S: Service + 'static> {
service: Rc<RefCell<S>>,
service: Cell<S>,
}
impl<S: Service + 'static> CloneableService<S> {
pub fn new(service: S) -> 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")]
extern crate webpki_roots;
mod cell;
pub mod cloneable;
pub mod connector;
pub mod counter;

View File

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

View File

@ -1,9 +1,7 @@
use std::cell::RefCell;
use std::rc::Rc;
use futures::{Async, Future, Poll};
use super::{IntoNewService, NewService, Service};
use cell::Cell;
/// Service for the `then` combinator, chaining a computation onto the end of
/// another service.
@ -11,7 +9,7 @@ use super::{IntoNewService, NewService, Service};
/// This is created by the `ServiceExt::then` method.
pub struct Then<A, B> {
a: A,
b: Rc<RefCell<B>>,
b: Cell<B>,
}
impl<A, B> Then<A, B>
@ -21,10 +19,7 @@ where
{
/// Create new `Then` combinator
pub fn new(a: A, b: B) -> Then<A, B> {
Then {
a,
b: Rc::new(RefCell::new(b)),
}
Then { a, b: Cell::new(b) }
}
}
@ -66,7 +61,7 @@ where
A: Service,
B: Service<Request = Result<A::Response, A::Error>>,
{
b: Rc<RefCell<B>>,
b: Cell<B>,
fut_b: Option<B::Future>,
fut_a: A::Future,
}
@ -76,7 +71,7 @@ where
A: Service,
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 {
b,
fut_a,
@ -243,6 +238,7 @@ mod tests {
use super::*;
use service::{NewServiceExt, ServiceExt};
#[derive(Clone)]
struct Srv1(Rc<Cell<usize>>);
impl Service for Srv1 {
type Request = Result<&'static str, &'static str>;
@ -263,7 +259,6 @@ mod tests {
}
}
#[derive(Clone)]
struct Srv2(Rc<Cell<usize>>);
impl Service for Srv2 {
@ -298,7 +293,7 @@ mod tests {
#[test]
fn test_call() {
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();
assert!(res.is_ok());
@ -315,7 +310,7 @@ mod tests {
let cnt2 = cnt.clone();
let blank = move || Ok::<_, ()>(Srv1(cnt2.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();
assert!(res.is_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 futures::future::{ok, FutureResult};
@ -7,11 +5,12 @@ use futures::{Async, Future, Poll};
use tokio_current_thread::spawn;
use tokio_timer::sleep;
use super::cell::Cell;
use super::service::{NewService, Service};
use super::Never;
#[derive(Clone, Debug)]
pub struct LowResTimer(Rc<RefCell<Inner>>);
pub struct LowResTimer(Cell<Inner>);
#[derive(Debug)]
struct Inner {
@ -30,7 +29,7 @@ impl Inner {
impl 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 {
@ -40,7 +39,7 @@ impl LowResTimer {
impl Default for LowResTimer {
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)]
pub struct LowResTimerService(Rc<RefCell<Inner>>);
pub struct LowResTimerService(Cell<Inner>);
impl 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