Skip to content

Instantly share code, notes, and snippets.

@Nemo157
Created January 16, 2020 12:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nemo157/b495b84b5b2f3134d19ad71ba5002066 to your computer and use it in GitHub Desktop.
Save Nemo157/b495b84b5b2f3134d19ad71ba5002066 to your computer and use it in GitHub Desktop.
From cb60e8590835718eedc3d14d3ad6527a42c588ce Mon Sep 17 00:00:00 2001
From: Wim Looman <wim@nemo157.com>
Date: Thu, 16 Jan 2020 13:17:13 +0100
Subject: [PATCH] Replace actix-service::cell::Cell<_> with Rc<RefCell<_>>
---
actix-service/src/and_then.rs | 17 ++++----
actix-service/src/and_then_apply_fn.rs | 19 +++++----
actix-service/src/apply_cfg.rs | 28 +++++++------
actix-service/src/cell.rs | 57 --------------------------
actix-service/src/lib.rs | 1 -
actix-service/src/then.rs | 15 +++----
6 files changed, 42 insertions(+), 95 deletions(-)
delete mode 100644 actix-service/src/cell.rs
diff --git a/actix-service/src/and_then.rs b/actix-service/src/and_then.rs
index 07ddc01..1ae183a 100644
--- a/actix-service/src/and_then.rs
+++ b/actix-service/src/and_then.rs
@@ -1,15 +1,16 @@
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
+use std::rc::Rc;
+use std::cell::RefCell;
use super::{Service, ServiceFactory};
-use crate::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 AndThenService<A, B>(Cell<A>, Cell<B>);
+pub struct AndThenService<A, B>(Rc<RefCell<A>>, Rc<RefCell<B>>);
impl<A, B> AndThenService<A, B> {
/// Create new `AndThen` combinator
@@ -18,7 +19,7 @@ impl<A, B> AndThenService<A, B> {
A: Service,
B: Service<Request = A::Response, Error = A::Error>,
{
- Self(Cell::new(a), Cell::new(b))
+ Self(Rc::new(RefCell::new(a)), Rc::new(RefCell::new(b)))
}
}
@@ -39,7 +40,7 @@ where
type Future = AndThenServiceResponse<A, B>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
- let not_ready = { !self.0.get_mut().poll_ready(cx)?.is_ready() };
+ let not_ready = { !self.0.borrow_mut().poll_ready(cx)?.is_ready() };
if !self.1.poll_ready(cx)?.is_ready() || not_ready {
Poll::Pending
} else {
@@ -49,7 +50,7 @@ where
fn call(&mut self, req: A::Request) -> Self::Future {
AndThenServiceResponse {
- state: State::A(self.0.get_mut().call(req), Some(self.1.clone())),
+ state: State::A(self.0.borrow_mut().call(req), Some(self.1.clone())),
}
}
}
@@ -70,7 +71,7 @@ where
A: Service,
B: Service<Request = A::Response, Error = A::Error>,
{
- A(#[pin] A::Future, Option<Cell<B>>),
+ A(#[pin] A::Future, Option<Rc<RefCell<B>>>),
B(#[pin] B::Future),
Empty,
}
@@ -90,9 +91,9 @@ where
match this.state.as_mut().project() {
State::A(fut, b) => match fut.poll(cx)? {
Poll::Ready(res) => {
- let mut b = b.take().unwrap();
+ let b = b.take().unwrap();
this.state.set(State::Empty); // drop fut A
- let fut = b.get_mut().call(res);
+ let fut = b.borrow_mut().call(res);
this.state.set(State::B(fut));
self.poll(cx)
}
diff --git a/actix-service/src/and_then_apply_fn.rs b/actix-service/src/and_then_apply_fn.rs
index b0aba07..ea2fe00 100644
--- a/actix-service/src/and_then_apply_fn.rs
+++ b/actix-service/src/and_then_apply_fn.rs
@@ -2,8 +2,9 @@ use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};
+use std::rc::Rc;
+use std::cell::RefCell;
-use crate::cell::Cell;
use crate::{Service, ServiceFactory};
/// `Apply` service combinator
@@ -16,7 +17,7 @@ where
Err: From<A::Error> + From<B::Error>,
{
a: A,
- b: Cell<(B, F)>,
+ b: Rc<RefCell<(B, F)>>,
r: PhantomData<(Fut, Res, Err)>,
}
@@ -32,7 +33,7 @@ where
pub(crate) fn new(a: A, b: B, f: F) -> Self {
Self {
a,
- b: Cell::new((b, f)),
+ b: Rc::new(RefCell::new((b, f))),
r: PhantomData,
}
}
@@ -70,7 +71,7 @@ where
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let not_ready = self.a.poll_ready(cx)?.is_pending();
- if self.b.get_mut().0.poll_ready(cx)?.is_pending() || not_ready {
+ if self.b.borrow_mut().0.poll_ready(cx)?.is_pending() || not_ready {
Poll::Pending
} else {
Poll::Ready(Ok(()))
@@ -108,7 +109,7 @@ where
Err: From<A::Error>,
Err: From<B::Error>,
{
- A(#[pin] A::Future, Option<Cell<(B, F)>>),
+ A(#[pin] A::Future, Option<Rc<RefCell<(B, F)>>>),
B(#[pin] Fut),
Empty,
}
@@ -131,10 +132,10 @@ where
match this.state.as_mut().project() {
State::A(fut, b) => match fut.poll(cx)? {
Poll::Ready(res) => {
- let mut b = b.take().unwrap();
+ let b = b.take().unwrap();
this.state.set(State::Empty);
- let b = b.get_mut();
- let fut = (&mut b.1)(res, &mut b.0);
+ let (b, f) = &mut *b.borrow_mut();
+ let fut = f(res, b);
this.state.set(State::B(fut));
self.poll(cx)
}
@@ -268,7 +269,7 @@ where
if this.a.is_some() && this.b.is_some() {
Poll::Ready(Ok(AndThenApplyFn {
a: this.a.take().unwrap(),
- b: Cell::new((this.b.take().unwrap(), this.f.clone())),
+ b: Rc::new(RefCell::new((this.b.take().unwrap(), this.f.clone()))),
r: PhantomData,
}))
} else {
diff --git a/actix-service/src/apply_cfg.rs b/actix-service/src/apply_cfg.rs
index a295639..d127ba8 100644
--- a/actix-service/src/apply_cfg.rs
+++ b/actix-service/src/apply_cfg.rs
@@ -2,8 +2,9 @@ use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};
+use std::rc::Rc;
+use std::cell::RefCell;
-use crate::cell::Cell;
use crate::{Service, ServiceFactory};
/// Convert `Fn(Config, &mut Service1) -> Future<Service2>` fn to a service factory
@@ -15,7 +16,7 @@ where
S: Service,
{
ApplyConfigService {
- srv: Cell::new((srv, f)),
+ srv: Rc::new(RefCell::new((srv, f))),
_t: PhantomData,
}
}
@@ -35,7 +36,7 @@ where
S: Service,
{
ApplyConfigServiceFactory {
- srv: Cell::new((factory, f)),
+ srv: Rc::new(RefCell::new((factory, f))),
_t: PhantomData,
}
}
@@ -48,7 +49,7 @@ where
R: Future<Output = Result<S, E>>,
S: Service,
{
- srv: Cell<(T, F)>,
+ srv: Rc<RefCell<(T, F)>>,
_t: PhantomData<(C, R, S)>,
}
@@ -84,10 +85,8 @@ where
type Future = R;
fn new_service(&self, cfg: C) -> Self::Future {
- unsafe {
- let srv = self.srv.get_mut_unsafe();
- (srv.1)(cfg, &mut srv.0)
- }
+ let (t, f) = &mut *self.srv.borrow_mut();
+ f(cfg, t)
}
}
@@ -99,7 +98,7 @@ where
R: Future<Output = Result<S, T::InitError>>,
S: Service,
{
- srv: Cell<(T, F)>,
+ srv: Rc<RefCell<(T, F)>>,
_t: PhantomData<(C, R, S)>,
}
@@ -139,7 +138,7 @@ where
ApplyConfigServiceFactoryResponse {
cfg: Some(cfg),
store: self.srv.clone(),
- state: State::A(self.srv.get_ref().0.new_service(())),
+ state: State::A(self.srv.borrow().0.new_service(())),
}
}
}
@@ -154,7 +153,7 @@ where
S: Service,
{
cfg: Option<C>,
- store: Cell<(T, F)>,
+ store: Rc<RefCell<(T, F)>>,
#[pin]
state: State<T, R, S>,
}
@@ -197,8 +196,11 @@ where
},
State::B(srv) => match srv.poll_ready(cx)? {
Poll::Ready(_) => {
- let fut = (this.store.get_mut().1)(this.cfg.take().unwrap(), srv);
- this.state.set(State::C(fut));
+ {
+ let (_, f) = &mut *this.store.borrow_mut();
+ let fut = f(this.cfg.take().unwrap(), srv);
+ this.state.set(State::C(fut));
+ }
self.poll(cx)
}
Poll::Pending => Poll::Pending,
diff --git a/actix-service/src/cell.rs b/actix-service/src/cell.rs
deleted file mode 100644
index 3bcac0b..0000000
--- a/actix-service/src/cell.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-//! Custom cell impl, internal use only
-use std::task::{Context, Poll};
-use std::{cell::UnsafeCell, fmt, rc::Rc};
-
-pub(crate) struct Cell<T> {
- inner: Rc<UnsafeCell<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)
- }
-}
-
-impl<T> Cell<T> {
- pub(crate) fn new(inner: T) -> Self {
- Self {
- inner: Rc::new(UnsafeCell::new(inner)),
- }
- }
-
- pub(crate) fn get_ref(&self) -> &T {
- unsafe { &*self.inner.as_ref().get() }
- }
-
- pub(crate) fn get_mut(&mut self) -> &mut T {
- unsafe { &mut *self.inner.as_ref().get() }
- }
-
- #[allow(clippy::mut_from_ref)]
- pub(crate) unsafe fn get_mut_unsafe(&self) -> &mut T {
- &mut *self.inner.as_ref().get()
- }
-}
-
-impl<T: crate::Service> crate::Service for Cell<T> {
- type Request = T::Request;
- type Response = T::Response;
- type Error = T::Error;
- type Future = T::Future;
-
- fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
- self.get_mut().poll_ready(cx)
- }
-
- fn call(&mut self, req: Self::Request) -> Self::Future {
- self.get_mut().call(req)
- }
-}
diff --git a/actix-service/src/lib.rs b/actix-service/src/lib.rs
index d018e0e..0c52f53 100644
--- a/actix-service/src/lib.rs
+++ b/actix-service/src/lib.rs
@@ -12,7 +12,6 @@ mod and_then_apply_fn;
mod apply;
mod apply_cfg;
pub mod boxed;
-mod cell;
mod fn_service;
mod map;
mod map_config;
diff --git a/actix-service/src/then.rs b/actix-service/src/then.rs
index 7cd5987..dd7620b 100644
--- a/actix-service/src/then.rs
+++ b/actix-service/src/then.rs
@@ -1,9 +1,10 @@
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
+use std::rc::Rc;
+use std::cell::RefCell;
use super::{Service, ServiceFactory};
-use crate::cell::Cell;
/// Service for the `then` combinator, chaining a computation onto the end of
/// another service.
@@ -11,7 +12,7 @@ use crate::cell::Cell;
/// This is created by the `ServiceExt::then` method.
pub struct ThenService<A, B> {
a: A,
- b: Cell<B>,
+ b: Rc<RefCell<B>>,
}
impl<A, B> ThenService<A, B> {
@@ -21,7 +22,7 @@ impl<A, B> ThenService<A, B> {
A: Service,
B: Service<Request = Result<A::Response, A::Error>, Error = A::Error>,
{
- Self { a, b: Cell::new(b) }
+ Self { a, b: Rc::new(RefCell::new(b)) }
}
}
@@ -49,7 +50,7 @@ where
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let not_ready = !self.a.poll_ready(ctx)?.is_ready();
- if !self.b.get_mut().poll_ready(ctx)?.is_ready() || not_ready {
+ if !self.b.borrow_mut().poll_ready(ctx)?.is_ready() || not_ready {
Poll::Pending
} else {
Poll::Ready(Ok(()))
@@ -79,7 +80,7 @@ where
A: Service,
B: Service<Request = Result<A::Response, A::Error>>,
{
- A(#[pin] A::Future, Option<Cell<B>>),
+ A(#[pin] A::Future, Option<Rc<RefCell<B>>>),
B(#[pin] B::Future),
Empty,
}
@@ -99,9 +100,9 @@ where
match this.state.as_mut().project() {
State::A(fut, b) => match fut.poll(cx) {
Poll::Ready(res) => {
- let mut b = b.take().unwrap();
+ let b = b.take().unwrap();
this.state.set(State::Empty); // drop fut A
- let fut = b.get_mut().call(res);
+ let fut = b.borrow_mut().call(res);
this.state.set(State::B(fut));
self.poll(cx)
}
--
2.24.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment