Skip to content

Commit

Permalink
add custom cell
Browse files Browse the repository at this point in the history
  • Loading branch information
fafhrd91 committed Oct 3, 2018
1 parent 79b525b commit 20b03a4
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 35 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ ssl = ["openssl", "tokio-openssl"]
# rustls
rust-tls = ["rustls", "tokio-rustls", "webpki", "webpki-roots"]

cell = []

[dependencies]
actix = "0.7.0"

Expand Down
62 changes: 62 additions & 0 deletions src/cell.rs
Original file line number Diff line number Diff line change
@@ -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()
}
}
8 changes: 3 additions & 5 deletions src/cloneable.rs
Original file line number Diff line number Diff line change
@@ -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),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
15 changes: 5 additions & 10 deletions src/service/and_then.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
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.
///
/// 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>
Expand All @@ -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) }
}
}

Expand Down Expand Up @@ -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,
}
Expand All @@ -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,
Expand Down
21 changes: 8 additions & 13 deletions src/service/then.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
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.
///
/// 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>
Expand All @@ -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) }
}
}

Expand Down Expand Up @@ -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,
}
Expand All @@ -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,
Expand Down Expand Up @@ -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>;
Expand All @@ -263,7 +259,6 @@ mod tests {
}
}

#[derive(Clone)]
struct Srv2(Rc<Cell<usize>>);

impl Service for Srv2 {
Expand Down Expand Up @@ -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());
Expand All @@ -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")));
Expand Down
13 changes: 6 additions & 7 deletions src/timer.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
use std::cell::RefCell;
use std::rc::Rc;
use std::time::{Duration, Instant};

use futures::future::{ok, FutureResult};
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 {
Expand All @@ -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 {
Expand All @@ -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))))
}
}

Expand All @@ -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
Expand Down

0 comments on commit 20b03a4

Please sign in to comment.