mirror of
https://github.com/fafhrd91/actix-net
synced 2024-11-27 18:02:58 +01:00
optimize service combinators memory layout
This commit is contained in:
parent
c6eb318536
commit
6f41b80cb4
@ -33,7 +33,7 @@ openssl = ["open-ssl", "tokio-openssl"]
|
||||
uri = ["http"]
|
||||
|
||||
[dependencies]
|
||||
actix-service = "1.0.0-alpha.2"
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
actix-codec = "0.2.0-alpha.2"
|
||||
actix-utils = "1.0.0-alpha.2"
|
||||
actix-rt = "1.0.0-alpha.2"
|
||||
|
@ -18,7 +18,7 @@ name = "actix_ioframe"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-service = "1.0.0-alpha.2"
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
actix-codec = "0.2.0-alpha.2"
|
||||
actix-utils = "1.0.0-alpha.2"
|
||||
actix-rt = "1.0.0-alpha.2"
|
||||
|
@ -21,7 +21,7 @@ path = "src/lib.rs"
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
actix-service = "1.0.0-alpha.2"
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
actix-rt = "1.0.0-alpha.2"
|
||||
actix-codec = "0.2.0-alpha.2"
|
||||
actix-utils = "1.0.0-alpha.2"
|
||||
|
@ -2,17 +2,24 @@
|
||||
|
||||
## [1.0.0-alpha.3] - 2019-12-xx
|
||||
|
||||
### Add missing Clone impls
|
||||
### Changed
|
||||
|
||||
### Restore `Transform::map_init_err()` combinator
|
||||
* Add missing Clone impls
|
||||
|
||||
* Restore `Transform::map_init_err()` combinator
|
||||
|
||||
* Restore `Service/Factory::apply_fn()` in form of `Pipeline/Factory::and_then_apply_fn()`
|
||||
|
||||
* Optimize service combinators and futures memory layout
|
||||
|
||||
### Restore `Service/Factory::apply_fn()` in form of `Pipeline/Factory::and_then_apply_fn()`
|
||||
|
||||
## [1.0.0-alpha.2] - 2019-12-02
|
||||
|
||||
### Use owned config value for service factory
|
||||
### Changed
|
||||
|
||||
### Renamed BoxedNewService/BoxedService to BoxServiceFactory/BoxService
|
||||
* Use owned config value for service factory
|
||||
|
||||
* Renamed BoxedNewService/BoxedService to BoxServiceFactory/BoxService
|
||||
|
||||
|
||||
## [1.0.0-alpha.1] - 2019-11-25
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-service"
|
||||
version = "1.0.0-alpha.2"
|
||||
version = "1.0.0-alpha.3"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Actix Service"
|
||||
keywords = ["network", "framework", "async", "futures"]
|
||||
@ -23,8 +23,8 @@ name = "actix_service"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
futures = "0.3.1"
|
||||
pin-project-lite = "0.1.1"
|
||||
futures-util = "0.3.1"
|
||||
pin-project = "0.4.6"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "1.0.0-alpha.2"
|
||||
|
@ -9,10 +9,7 @@ use crate::cell::Cell;
|
||||
/// of another service which completes successfully.
|
||||
///
|
||||
/// This is created by the `ServiceExt::and_then` method.
|
||||
pub struct AndThenService<A, B> {
|
||||
a: A,
|
||||
b: Cell<B>,
|
||||
}
|
||||
pub struct AndThenService<A, B>(Cell<(A, B)>);
|
||||
|
||||
impl<A, B> AndThenService<A, B> {
|
||||
/// Create new `AndThen` combinator
|
||||
@ -21,19 +18,13 @@ impl<A, B> AndThenService<A, B> {
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
Self { a, b: Cell::new(b) }
|
||||
Self(Cell::new((a, b)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> Clone for AndThenService<A, B>
|
||||
where
|
||||
A: Clone,
|
||||
{
|
||||
impl<A, B> Clone for AndThenService<A, B> {
|
||||
fn clone(&self) -> Self {
|
||||
AndThenService {
|
||||
a: self.a.clone(),
|
||||
b: self.b.clone(),
|
||||
}
|
||||
AndThenService(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,8 +39,10 @@ where
|
||||
type Future = AndThenServiceResponse<A, B>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
let not_ready = !self.a.poll_ready(cx)?.is_ready();
|
||||
if !self.b.get_mut().poll_ready(cx)?.is_ready() || not_ready {
|
||||
let srv = self.0.get_mut();
|
||||
|
||||
let not_ready = !srv.0.poll_ready(cx)?.is_ready();
|
||||
if !srv.1.poll_ready(cx)?.is_ready() || not_ready {
|
||||
Poll::Pending
|
||||
} else {
|
||||
Poll::Ready(Ok(()))
|
||||
@ -57,36 +50,30 @@ where
|
||||
}
|
||||
|
||||
fn call(&mut self, req: A::Request) -> Self::Future {
|
||||
AndThenServiceResponse::new(self.a.call(req), self.b.clone())
|
||||
AndThenServiceResponse {
|
||||
state: State::A(self.0.get_mut().0.call(req), self.0.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct AndThenServiceResponse<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
b: Cell<B>,
|
||||
#[pin]
|
||||
fut_b: Option<B::Future>,
|
||||
#[pin]
|
||||
fut_a: Option<A::Future>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> AndThenServiceResponse<A, B>
|
||||
#[pin_project::pin_project]
|
||||
pub struct AndThenServiceResponse<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
fn new(a: A::Future, b: Cell<B>) -> Self {
|
||||
AndThenServiceResponse {
|
||||
b,
|
||||
fut_a: Some(a),
|
||||
fut_b: None,
|
||||
}
|
||||
}
|
||||
#[pin]
|
||||
state: State<A, B>,
|
||||
}
|
||||
|
||||
#[pin_project::pin_project]
|
||||
enum State<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
A(#[pin] A::Future, Cell<(A, B)>),
|
||||
B(#[pin] B::Future),
|
||||
}
|
||||
|
||||
impl<A, B> Future for AndThenServiceResponse<A, B>
|
||||
@ -96,28 +83,21 @@ where
|
||||
{
|
||||
type Output = Result<B::Response, A::Error>;
|
||||
|
||||
#[pin_project::project]
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
||||
loop {
|
||||
if let Some(fut) = this.fut_b.as_pin_mut() {
|
||||
return fut.poll(cx);
|
||||
}
|
||||
|
||||
match this
|
||||
.fut_a
|
||||
.as_pin_mut()
|
||||
.expect("Bug in actix-service")
|
||||
.poll(cx)
|
||||
{
|
||||
Poll::Ready(Ok(resp)) => {
|
||||
this = self.as_mut().project();
|
||||
this.fut_a.set(None);
|
||||
this.fut_b.set(Some(this.b.get_mut().call(resp)));
|
||||
}
|
||||
Poll::Ready(Err(e)) => return Poll::Ready(Err(e)),
|
||||
Poll::Pending => return Poll::Pending,
|
||||
#[project]
|
||||
match this.state.as_mut().project() {
|
||||
State::A(fut, b) => match fut.poll(cx)? {
|
||||
Poll::Ready(res) => {
|
||||
let fut = b.get_mut().1.call(res);
|
||||
this.state.set(State::B(fut));
|
||||
self.poll(cx)
|
||||
}
|
||||
Poll::Pending => Poll::Pending,
|
||||
},
|
||||
State::B(fut) => fut.poll(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -202,20 +182,19 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct AndThenServiceFactoryResponse<A, B>
|
||||
where
|
||||
#[pin_project::pin_project]
|
||||
pub struct AndThenServiceFactoryResponse<A, B>
|
||||
where
|
||||
A: ServiceFactory,
|
||||
B: ServiceFactory<Request = A::Response>,
|
||||
{
|
||||
#[pin]
|
||||
fut_b: B::Future,
|
||||
{
|
||||
#[pin]
|
||||
fut_a: A::Future,
|
||||
#[pin]
|
||||
fut_b: B::Future,
|
||||
|
||||
a: Option<A::Service>,
|
||||
b: Option<B::Service>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> AndThenServiceFactoryResponse<A, B>
|
||||
@ -270,7 +249,7 @@ mod tests {
|
||||
use std::rc::Rc;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use futures::future::{lazy, ok, ready, Ready};
|
||||
use futures_util::future::{lazy, ok, ready, Ready};
|
||||
|
||||
use crate::{factory_fn, pipeline, pipeline_factory, Service, ServiceFactory};
|
||||
|
||||
|
@ -3,8 +3,6 @@ use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use futures::ready;
|
||||
|
||||
use crate::cell::Cell;
|
||||
use crate::{Service, ServiceFactory};
|
||||
|
||||
@ -18,8 +16,7 @@ where
|
||||
Err: From<A::Error> + From<B::Error>,
|
||||
{
|
||||
a: A,
|
||||
b: Cell<B>,
|
||||
f: Cell<F>,
|
||||
b: Cell<(B, F)>,
|
||||
r: PhantomData<(Fut, Res, Err)>,
|
||||
}
|
||||
|
||||
@ -35,8 +32,7 @@ where
|
||||
pub(crate) fn new(a: A, b: B, f: F) -> Self {
|
||||
Self {
|
||||
a,
|
||||
f: Cell::new(f),
|
||||
b: Cell::new(b),
|
||||
b: Cell::new((b, f)),
|
||||
r: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -54,7 +50,6 @@ where
|
||||
AndThenApplyFn {
|
||||
a: self.a.clone(),
|
||||
b: self.b.clone(),
|
||||
f: self.f.clone(),
|
||||
r: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -75,7 +70,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().poll_ready(cx)?.is_pending() || not_ready {
|
||||
if self.b.get_mut().0.poll_ready(cx)?.is_pending() || not_ready {
|
||||
Poll::Pending
|
||||
} else {
|
||||
Poll::Ready(Ok(()))
|
||||
@ -84,31 +79,37 @@ where
|
||||
|
||||
fn call(&mut self, req: A::Request) -> Self::Future {
|
||||
AndThenApplyFnFuture {
|
||||
b: self.b.clone(),
|
||||
f: self.f.clone(),
|
||||
fut_a: Some(self.a.call(req)),
|
||||
fut_b: None,
|
||||
state: State::A(self.a.call(req), self.b.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct AndThenApplyFnFuture<A, B, F, Fut, Res, Err>
|
||||
where
|
||||
#[pin_project::pin_project]
|
||||
pub struct AndThenApplyFnFuture<A, B, F, Fut, Res, Err>
|
||||
where
|
||||
A: Service,
|
||||
B: Service,
|
||||
F: FnMut(A::Response, &mut B) -> Fut,
|
||||
Fut: Future<Output = Result<Res, Err>>,
|
||||
Err: From<A::Error>,
|
||||
Err: From<B::Error>,
|
||||
{
|
||||
b: Cell<B>,
|
||||
f: Cell<F>,
|
||||
{
|
||||
#[pin]
|
||||
fut_a: Option<A::Future>,
|
||||
#[pin]
|
||||
fut_b: Option<Fut>,
|
||||
}
|
||||
state: State<A, B, F, Fut, Res, Err>,
|
||||
}
|
||||
|
||||
#[pin_project::pin_project]
|
||||
enum State<A, B, F, Fut, Res, Err>
|
||||
where
|
||||
A: Service,
|
||||
B: Service,
|
||||
F: FnMut(A::Response, &mut B) -> Fut,
|
||||
Fut: Future<Output = Result<Res, Err>>,
|
||||
Err: From<A::Error>,
|
||||
Err: From<B::Error>,
|
||||
{
|
||||
A(#[pin] A::Future, Cell<(B, F)>),
|
||||
B(#[pin] Fut),
|
||||
}
|
||||
|
||||
impl<A, B, F, Fut, Res, Err> Future for AndThenApplyFnFuture<A, B, F, Fut, Res, Err>
|
||||
@ -121,28 +122,22 @@ where
|
||||
{
|
||||
type Output = Result<Res, Err>;
|
||||
|
||||
#[pin_project::project]
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
||||
if let Some(fut) = this.fut_b.as_pin_mut() {
|
||||
return Poll::Ready(ready!(fut.poll(cx)).map_err(|e| e.into()));
|
||||
}
|
||||
|
||||
match this
|
||||
.fut_a
|
||||
.as_pin_mut()
|
||||
.expect("Bug in actix-service")
|
||||
.poll(cx)
|
||||
{
|
||||
Poll::Ready(Ok(resp)) => {
|
||||
this = self.as_mut().project();
|
||||
this.fut_b
|
||||
.set(Some((&mut *this.f.get_mut())(resp, this.b.get_mut())));
|
||||
this.fut_a.set(None);
|
||||
#[project]
|
||||
match this.state.as_mut().project() {
|
||||
State::A(fut, b) => match fut.poll(cx)? {
|
||||
Poll::Ready(res) => {
|
||||
let b = b.get_mut();
|
||||
let fut = (&mut b.1)(res, &mut b.0);
|
||||
this.state.set(State::B(fut));
|
||||
self.poll(cx)
|
||||
}
|
||||
Poll::Pending => Poll::Pending,
|
||||
Poll::Ready(Err(err)) => Poll::Ready(Err(err.into())),
|
||||
},
|
||||
State::B(fut) => fut.poll(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -151,7 +146,7 @@ where
|
||||
pub struct AndThenApplyFnFactory<A, B, F, Fut, Res, Err> {
|
||||
a: A,
|
||||
b: B,
|
||||
f: Cell<F>,
|
||||
f: F,
|
||||
r: PhantomData<(Fut, Res, Err)>,
|
||||
}
|
||||
|
||||
@ -159,7 +154,7 @@ impl<A, B, F, Fut, Res, Err> AndThenApplyFnFactory<A, B, F, Fut, Res, Err>
|
||||
where
|
||||
A: ServiceFactory,
|
||||
B: ServiceFactory<Config = A::Config, InitError = A::InitError>,
|
||||
F: FnMut(A::Response, &mut B::Service) -> Fut,
|
||||
F: FnMut(A::Response, &mut B::Service) -> Fut + Clone,
|
||||
Fut: Future<Output = Result<Res, Err>>,
|
||||
Err: From<A::Error> + From<B::Error>,
|
||||
{
|
||||
@ -168,7 +163,7 @@ where
|
||||
Self {
|
||||
a: a,
|
||||
b: b,
|
||||
f: Cell::new(f),
|
||||
f: f,
|
||||
r: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -178,6 +173,7 @@ impl<A, B, F, Fut, Res, Err> Clone for AndThenApplyFnFactory<A, B, F, Fut, Res,
|
||||
where
|
||||
A: Clone,
|
||||
B: Clone,
|
||||
F: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
@ -194,7 +190,7 @@ where
|
||||
A: ServiceFactory,
|
||||
A::Config: Clone,
|
||||
B: ServiceFactory<Config = A::Config, InitError = A::InitError>,
|
||||
F: FnMut(A::Response, &mut B::Service) -> Fut,
|
||||
F: FnMut(A::Response, &mut B::Service) -> Fut + Clone,
|
||||
Fut: Future<Output = Result<Res, Err>>,
|
||||
Err: From<A::Error> + From<B::Error>,
|
||||
{
|
||||
@ -217,31 +213,30 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct AndThenApplyFnFactoryResponse<A, B, F, Fut, Res, Err>
|
||||
where
|
||||
#[pin_project::pin_project]
|
||||
pub struct AndThenApplyFnFactoryResponse<A, B, F, Fut, Res, Err>
|
||||
where
|
||||
A: ServiceFactory,
|
||||
B: ServiceFactory<Config = A::Config, InitError = A::InitError>,
|
||||
F: FnMut(A::Response, &mut B::Service) -> Fut,
|
||||
F: FnMut(A::Response, &mut B::Service) -> Fut + Clone,
|
||||
Fut: Future<Output = Result<Res, Err>>,
|
||||
Err: From<A::Error>,
|
||||
Err: From<B::Error>,
|
||||
{
|
||||
{
|
||||
#[pin]
|
||||
fut_b: B::Future,
|
||||
#[pin]
|
||||
fut_a: A::Future,
|
||||
f: Cell<F>,
|
||||
f: F,
|
||||
a: Option<A::Service>,
|
||||
b: Option<B::Service>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, F, Fut, Res, Err> Future for AndThenApplyFnFactoryResponse<A, B, F, Fut, Res, Err>
|
||||
where
|
||||
A: ServiceFactory,
|
||||
B: ServiceFactory<Config = A::Config, InitError = A::InitError>,
|
||||
F: FnMut(A::Response, &mut B::Service) -> Fut,
|
||||
F: FnMut(A::Response, &mut B::Service) -> Fut + Clone,
|
||||
Fut: Future<Output = Result<Res, Err>>,
|
||||
Err: From<A::Error> + From<B::Error>,
|
||||
{
|
||||
@ -265,9 +260,8 @@ where
|
||||
|
||||
if this.a.is_some() && this.b.is_some() {
|
||||
Poll::Ready(Ok(AndThenApplyFn {
|
||||
f: this.f.clone(),
|
||||
a: this.a.take().unwrap(),
|
||||
b: Cell::new(this.b.take().unwrap()),
|
||||
b: Cell::new((this.b.take().unwrap(), this.f.clone())),
|
||||
r: PhantomData,
|
||||
}))
|
||||
} else {
|
||||
@ -280,7 +274,7 @@ where
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use futures::future::{lazy, ok, Ready, TryFutureExt};
|
||||
use futures_util::future::{lazy, ok, Ready, TryFutureExt};
|
||||
|
||||
use crate::{pipeline, pipeline_factory, service_fn2, Service, ServiceFactory};
|
||||
|
||||
|
@ -67,8 +67,8 @@ where
|
||||
type Error = Err;
|
||||
type Future = R;
|
||||
|
||||
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(futures::ready!(self.service.poll_ready(ctx)))
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(futures_util::ready!(self.service.poll_ready(cx)))
|
||||
}
|
||||
|
||||
fn call(&mut self, req: In) -> Self::Future {
|
||||
@ -139,24 +139,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct ApplyServiceFactoryResponse<T, F, R, In, Out, Err>
|
||||
where
|
||||
#[pin_project::pin_project]
|
||||
pub struct ApplyServiceFactoryResponse<T, F, R, In, Out, Err>
|
||||
where
|
||||
T: ServiceFactory<Error = Err>,
|
||||
F: FnMut(In, &mut T::Service) -> R,
|
||||
R: Future<Output = Result<Out, Err>>,
|
||||
{
|
||||
{
|
||||
#[pin]
|
||||
fut: T::Future,
|
||||
f: Option<F>,
|
||||
r: PhantomData<(In, Out)>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, F, R, In, Out, Err> ApplyServiceFactoryResponse<T, F, R, In, Out, Err>
|
||||
where
|
||||
T: ServiceFactory<Error = Err>,
|
||||
F: FnMut(In, &mut T::Service) -> R + Clone,
|
||||
F: FnMut(In, &mut T::Service) -> R,
|
||||
R: Future<Output = Result<Out, Err>>,
|
||||
{
|
||||
fn new(fut: T::Future, f: F) -> Self {
|
||||
@ -171,7 +170,7 @@ where
|
||||
impl<T, F, R, In, Out, Err> Future for ApplyServiceFactoryResponse<T, F, R, In, Out, Err>
|
||||
where
|
||||
T: ServiceFactory<Error = Err>,
|
||||
F: FnMut(In, &mut T::Service) -> R + Clone,
|
||||
F: FnMut(In, &mut T::Service) -> R,
|
||||
R: Future<Output = Result<Out, Err>>,
|
||||
{
|
||||
type Output = Result<Apply<T::Service, F, R, In, Out, Err>, T::InitError>;
|
||||
@ -191,7 +190,7 @@ where
|
||||
mod tests {
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use futures::future::{lazy, ok, Ready};
|
||||
use futures_util::future::{lazy, ok, Ready};
|
||||
|
||||
use super::*;
|
||||
use crate::{pipeline, pipeline_factory, Service, ServiceFactory};
|
||||
|
@ -15,8 +15,7 @@ where
|
||||
S: Service,
|
||||
{
|
||||
ApplyConfigService {
|
||||
f: Cell::new(f),
|
||||
srv: Cell::new(srv),
|
||||
srv: Cell::new((srv, f)),
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -35,8 +34,7 @@ where
|
||||
S: Service,
|
||||
{
|
||||
ApplyConfigServiceFactory {
|
||||
f: Cell::new(f),
|
||||
srv: Cell::new(srv),
|
||||
srv: Cell::new((srv, f)),
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -49,8 +47,7 @@ where
|
||||
R: Future<Output = Result<S, E>>,
|
||||
S: Service,
|
||||
{
|
||||
f: Cell<F>,
|
||||
srv: Cell<T>,
|
||||
srv: Cell<(T, F)>,
|
||||
_t: PhantomData<(C, R, S)>,
|
||||
}
|
||||
|
||||
@ -63,7 +60,6 @@ where
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
ApplyConfigService {
|
||||
f: self.f.clone(),
|
||||
srv: self.srv.clone(),
|
||||
_t: PhantomData,
|
||||
}
|
||||
@ -87,7 +83,10 @@ where
|
||||
type Future = R;
|
||||
|
||||
fn new_service(&self, cfg: C) -> Self::Future {
|
||||
unsafe { (self.f.get_mut_unsafe())(cfg, self.srv.get_mut_unsafe()) }
|
||||
unsafe {
|
||||
let srv = self.srv.get_mut_unsafe();
|
||||
(srv.1)(cfg, &mut srv.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,8 +98,7 @@ where
|
||||
R: Future<Output = Result<S, T::InitError>>,
|
||||
S: Service,
|
||||
{
|
||||
f: Cell<F>,
|
||||
srv: Cell<T>,
|
||||
srv: Cell<(T, F)>,
|
||||
_t: PhantomData<(C, R, S)>,
|
||||
}
|
||||
|
||||
@ -113,7 +111,6 @@ where
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
f: self.f.clone(),
|
||||
srv: self.srv.clone(),
|
||||
_t: PhantomData,
|
||||
}
|
||||
@ -139,34 +136,39 @@ where
|
||||
|
||||
fn new_service(&self, cfg: C) -> Self::Future {
|
||||
ApplyConfigServiceFactoryResponse {
|
||||
f: self.f.clone(),
|
||||
cfg: Some(cfg),
|
||||
fut: None,
|
||||
srv: None,
|
||||
srv_fut: Some(self.srv.get_ref().new_service(())),
|
||||
_t: PhantomData,
|
||||
store: self.srv.clone(),
|
||||
state: State::A(self.srv.get_ref().0.new_service(())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct ApplyConfigServiceFactoryResponse<F, C, T, R, S>
|
||||
where
|
||||
#[pin_project::pin_project]
|
||||
pub struct ApplyConfigServiceFactoryResponse<F, C, T, R, S>
|
||||
where
|
||||
F: FnMut(C, &mut T::Service) -> R,
|
||||
T: ServiceFactory<Config = ()>,
|
||||
T::InitError: From<T::Error>,
|
||||
R: Future<Output = Result<S, T::InitError>>,
|
||||
S: Service,
|
||||
{
|
||||
{
|
||||
cfg: Option<C>,
|
||||
f: Cell<F>,
|
||||
srv: Option<T::Service>,
|
||||
store: Cell<(T, F)>,
|
||||
#[pin]
|
||||
srv_fut: Option<T::Future>,
|
||||
#[pin]
|
||||
fut: Option<R>,
|
||||
_t: PhantomData<(S,)>,
|
||||
}
|
||||
state: State<T, R, S>,
|
||||
}
|
||||
|
||||
#[pin_project::pin_project]
|
||||
enum State<T, R, S>
|
||||
where
|
||||
T: ServiceFactory<Config = ()>,
|
||||
T::InitError: From<T::Error>,
|
||||
R: Future<Output = Result<S, T::InitError>>,
|
||||
S: Service,
|
||||
{
|
||||
A(#[pin] T::Future),
|
||||
B(T::Service),
|
||||
C(#[pin] R),
|
||||
}
|
||||
|
||||
impl<F, C, T, R, S> Future for ApplyConfigServiceFactoryResponse<F, C, T, R, S>
|
||||
@ -179,37 +181,28 @@ where
|
||||
{
|
||||
type Output = Result<S, T::InitError>;
|
||||
|
||||
#[pin_project::project]
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
||||
loop {
|
||||
if let Some(fut) = this.srv_fut.as_pin_mut() {
|
||||
match fut.poll(cx)? {
|
||||
Poll::Pending => return Poll::Pending,
|
||||
#[project]
|
||||
match this.state.as_mut().project() {
|
||||
State::A(fut) => match fut.poll(cx)? {
|
||||
Poll::Pending => Poll::Pending,
|
||||
Poll::Ready(srv) => {
|
||||
this = self.as_mut().project();
|
||||
this.srv_fut.set(None);
|
||||
*this.srv = Some(srv);
|
||||
continue;
|
||||
this.state.set(State::B(srv));
|
||||
self.poll(cx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(fut) = this.fut.as_pin_mut() {
|
||||
return fut.poll(cx);
|
||||
} else if let Some(srv) = this.srv {
|
||||
match srv.poll_ready(cx)? {
|
||||
},
|
||||
State::B(srv) => match srv.poll_ready(cx)? {
|
||||
Poll::Ready(_) => {
|
||||
let fut = this.f.get_mut()(this.cfg.take().unwrap(), srv);
|
||||
this = self.as_mut().project();
|
||||
this.fut.set(Some(fut));
|
||||
continue;
|
||||
}
|
||||
Poll::Pending => return Poll::Pending,
|
||||
}
|
||||
} else {
|
||||
return Poll::Pending;
|
||||
let fut = (this.store.get_mut().1)(this.cfg.take().unwrap(), srv);
|
||||
this.state.set(State::C(fut));
|
||||
self.poll(cx)
|
||||
}
|
||||
Poll::Pending => Poll::Pending,
|
||||
},
|
||||
State::C(fut) => fut.poll(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use futures::future::FutureExt;
|
||||
use futures_util::future::FutureExt;
|
||||
|
||||
use crate::{Service, ServiceFactory};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
//! Custom cell impl, internal use only
|
||||
use std::task::{Context, Poll};
|
||||
use std::{cell::UnsafeCell, fmt, rc::Rc};
|
||||
|
||||
pub(crate) struct Cell<T> {
|
||||
@ -39,3 +40,18 @@ impl<T> Cell<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)
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use futures::future::{ok, Ready};
|
||||
use futures_util::future::{ok, Ready};
|
||||
|
||||
use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory};
|
||||
|
||||
|
@ -1,9 +1,6 @@
|
||||
#![deny(rust_2018_idioms, warnings)]
|
||||
#![allow(clippy::type_complexity)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate pin_project_lite;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::rc::Rc;
|
||||
|
@ -62,16 +62,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct MapFuture<A, F, Response>
|
||||
where
|
||||
#[pin_project::pin_project]
|
||||
pub struct MapFuture<A, F, Response>
|
||||
where
|
||||
A: Service,
|
||||
F: FnMut(A::Response) -> Response,
|
||||
{
|
||||
{
|
||||
f: F,
|
||||
#[pin]
|
||||
fut: A::Future,
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, F, Response> MapFuture<A, F, Response>
|
||||
@ -157,16 +156,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct MapServiceFuture<A, F, Res>
|
||||
where
|
||||
#[pin_project::pin_project]
|
||||
pub struct MapServiceFuture<A, F, Res>
|
||||
where
|
||||
A: ServiceFactory,
|
||||
F: FnMut(A::Response) -> Res,
|
||||
{
|
||||
{
|
||||
#[pin]
|
||||
fut: A::Future,
|
||||
f: Option<F>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, F, Res> MapServiceFuture<A, F, Res>
|
||||
@ -199,7 +197,7 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use futures::future::{lazy, ok, Ready};
|
||||
use futures_util::future::{lazy, ok, Ready};
|
||||
|
||||
use super::*;
|
||||
use crate::{IntoServiceFactory, Service, ServiceFactory};
|
||||
|
@ -63,16 +63,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct MapErrFuture<A, F, E>
|
||||
where
|
||||
#[pin_project::pin_project]
|
||||
pub struct MapErrFuture<A, F, E>
|
||||
where
|
||||
A: Service,
|
||||
F: Fn(A::Error) -> E,
|
||||
{
|
||||
{
|
||||
f: F,
|
||||
#[pin]
|
||||
fut: A::Future,
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, F, E> MapErrFuture<A, F, E>
|
||||
@ -160,16 +159,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct MapErrServiceFuture<A, F, E>
|
||||
where
|
||||
#[pin_project::pin_project]
|
||||
pub struct MapErrServiceFuture<A, F, E>
|
||||
where
|
||||
A: ServiceFactory,
|
||||
F: Fn(A::Error) -> E,
|
||||
{
|
||||
{
|
||||
#[pin]
|
||||
fut: A::Future,
|
||||
f: F,
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, F, E> MapErrServiceFuture<A, F, E>
|
||||
@ -201,7 +199,7 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use futures::future::{err, lazy, ok, Ready};
|
||||
use futures_util::future::{err, lazy, ok, Ready};
|
||||
|
||||
use super::*;
|
||||
use crate::{IntoServiceFactory, Service, ServiceFactory};
|
||||
|
@ -60,16 +60,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct MapInitErrFuture<A, F, E>
|
||||
where
|
||||
#[pin_project::pin_project]
|
||||
pub struct MapInitErrFuture<A, F, E>
|
||||
where
|
||||
A: ServiceFactory,
|
||||
F: Fn(A::InitError) -> E,
|
||||
{
|
||||
{
|
||||
f: F,
|
||||
#[pin]
|
||||
fut: A::Future,
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, F, E> MapInitErrFuture<A, F, E>
|
||||
|
@ -197,7 +197,7 @@ impl<T: ServiceFactory> PipelineFactory<T> {
|
||||
T::Config: Clone,
|
||||
I: IntoServiceFactory<U>,
|
||||
U: ServiceFactory<Config = T::Config, InitError = T::InitError>,
|
||||
F: FnMut(T::Response, &mut U::Service) -> Fut,
|
||||
F: FnMut(T::Response, &mut U::Service) -> Fut + Clone,
|
||||
Fut: Future<Output = Result<Res, Err>>,
|
||||
Err: From<T::Error> + From<U::Error>,
|
||||
{
|
||||
|
@ -57,36 +57,30 @@ where
|
||||
}
|
||||
|
||||
fn call(&mut self, req: A::Request) -> Self::Future {
|
||||
ThenServiceResponse::new(self.a.call(req), self.b.clone())
|
||||
ThenServiceResponse {
|
||||
state: ThenServiceResponseState::A(self.a.call(req), self.b.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct ThenServiceResponse<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = Result<A::Response, A::Error>>,
|
||||
{
|
||||
b: Cell<B>,
|
||||
#[pin]
|
||||
fut_b: Option<B::Future>,
|
||||
#[pin]
|
||||
fut_a: Option<A::Future>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> ThenServiceResponse<A, B>
|
||||
#[pin_project::pin_project]
|
||||
pub struct ThenServiceResponse<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = Result<A::Response, A::Error>>,
|
||||
{
|
||||
fn new(a: A::Future, b: Cell<B>) -> Self {
|
||||
ThenServiceResponse {
|
||||
b,
|
||||
fut_a: Some(a),
|
||||
fut_b: None,
|
||||
}
|
||||
}
|
||||
#[pin]
|
||||
state: ThenServiceResponseState<A, B>,
|
||||
}
|
||||
|
||||
#[pin_project::pin_project]
|
||||
enum ThenServiceResponseState<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = Result<A::Response, A::Error>>,
|
||||
{
|
||||
A(#[pin] A::Future, Cell<B>),
|
||||
B(#[pin] B::Future),
|
||||
}
|
||||
|
||||
impl<A, B> Future for ThenServiceResponse<A, B>
|
||||
@ -96,27 +90,21 @@ where
|
||||
{
|
||||
type Output = Result<B::Response, B::Error>;
|
||||
|
||||
#[pin_project::project]
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
||||
loop {
|
||||
if let Some(fut) = this.fut_b.as_pin_mut() {
|
||||
return fut.poll(cx);
|
||||
}
|
||||
|
||||
match this
|
||||
.fut_a
|
||||
.as_pin_mut()
|
||||
.expect("Bug in actix-service")
|
||||
.poll(cx)
|
||||
{
|
||||
Poll::Ready(r) => {
|
||||
this = self.as_mut().project();
|
||||
this.fut_b.set(Some(this.b.get_mut().call(r)));
|
||||
}
|
||||
|
||||
Poll::Pending => return Poll::Pending,
|
||||
#[project]
|
||||
match this.state.as_mut().project() {
|
||||
ThenServiceResponseState::A(fut, b) => match fut.poll(cx) {
|
||||
Poll::Ready(res) => {
|
||||
let fut = b.get_mut().call(res);
|
||||
this.state.set(ThenServiceResponseState::B(fut));
|
||||
self.poll(cx)
|
||||
}
|
||||
Poll::Pending => Poll::Pending,
|
||||
},
|
||||
ThenServiceResponseState::B(fut) => fut.poll(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,23 +173,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct ThenServiceFactoryResponse<A, B>
|
||||
where
|
||||
#[pin_project::pin_project]
|
||||
pub struct ThenServiceFactoryResponse<A, B>
|
||||
where
|
||||
A: ServiceFactory,
|
||||
B: ServiceFactory<
|
||||
Config = A::Config,
|
||||
Request = Result<A::Response, A::Error>,
|
||||
Error = A::Error,
|
||||
InitError = A::InitError>
|
||||
{
|
||||
InitError = A::InitError,
|
||||
>,
|
||||
{
|
||||
#[pin]
|
||||
fut_b: B::Future,
|
||||
#[pin]
|
||||
fut_a: A::Future,
|
||||
a: Option<A::Service>,
|
||||
b: Option<B::Service>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> ThenServiceFactoryResponse<A, B>
|
||||
@ -266,7 +254,7 @@ mod tests {
|
||||
use std::rc::Rc;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use futures::future::{err, lazy, ok, ready, Ready};
|
||||
use futures_util::future::{err, lazy, ok, ready, Ready};
|
||||
|
||||
use crate::{pipeline, pipeline_factory, Service, ServiceFactory};
|
||||
|
||||
|
@ -94,10 +94,7 @@ where
|
||||
}
|
||||
|
||||
/// `Apply` transform to new service
|
||||
pub struct ApplyTransform<T, S> {
|
||||
s: Rc<S>,
|
||||
t: Rc<T>,
|
||||
}
|
||||
pub struct ApplyTransform<T, S>(Rc<(T, S)>);
|
||||
|
||||
impl<T, S> ApplyTransform<T, S>
|
||||
where
|
||||
@ -106,19 +103,13 @@ where
|
||||
{
|
||||
/// Create new `ApplyTransform` new service instance
|
||||
fn new(t: T, service: S) -> Self {
|
||||
Self {
|
||||
s: Rc::new(service),
|
||||
t: Rc::new(t),
|
||||
}
|
||||
Self(Rc::new((t, service)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> Clone for ApplyTransform<T, S> {
|
||||
fn clone(&self) -> Self {
|
||||
ApplyTransform {
|
||||
s: self.s.clone(),
|
||||
t: self.t.clone(),
|
||||
}
|
||||
ApplyTransform(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,25 +129,31 @@ where
|
||||
|
||||
fn new_service(&self, cfg: S::Config) -> Self::Future {
|
||||
ApplyTransformFuture {
|
||||
t_cell: self.t.clone(),
|
||||
fut_a: self.s.new_service(cfg),
|
||||
fut_t: None,
|
||||
store: self.0.clone(),
|
||||
state: ApplyTransformFutureState::A(self.0.as_ref().1.new_service(cfg)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct ApplyTransformFuture<T, S>
|
||||
where
|
||||
#[pin_project::pin_project]
|
||||
pub struct ApplyTransformFuture<T, S>
|
||||
where
|
||||
S: ServiceFactory,
|
||||
T: Transform<S::Service, InitError = S::InitError>,
|
||||
{
|
||||
{
|
||||
store: Rc<(T, S)>,
|
||||
#[pin]
|
||||
fut_a: S::Future,
|
||||
#[pin]
|
||||
fut_t: Option<T::Future>,
|
||||
t_cell: Rc<T>,
|
||||
}
|
||||
state: ApplyTransformFutureState<T, S>,
|
||||
}
|
||||
|
||||
#[pin_project::pin_project]
|
||||
pub enum ApplyTransformFutureState<T, S>
|
||||
where
|
||||
S: ServiceFactory,
|
||||
T: Transform<S::Service, InitError = S::InitError>,
|
||||
{
|
||||
A(#[pin] S::Future),
|
||||
B(#[pin] T::Future),
|
||||
}
|
||||
|
||||
impl<T, S> Future for ApplyTransformFuture<T, S>
|
||||
@ -166,20 +163,21 @@ where
|
||||
{
|
||||
type Output = Result<T::Transform, T::InitError>;
|
||||
|
||||
#[pin_project::project]
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
||||
if let Some(fut) = this.fut_t.as_pin_mut() {
|
||||
return fut.poll(cx);
|
||||
#[project]
|
||||
match this.state.as_mut().project() {
|
||||
ApplyTransformFutureState::A(fut) => match fut.poll(cx)? {
|
||||
Poll::Ready(srv) => {
|
||||
let fut = this.store.0.new_transform(srv);
|
||||
this.state.set(ApplyTransformFutureState::B(fut));
|
||||
self.poll(cx)
|
||||
}
|
||||
|
||||
if let Poll::Ready(service) = this.fut_a.poll(cx)? {
|
||||
let fut = this.t_cell.new_transform(service);
|
||||
this = self.as_mut().project();
|
||||
this.fut_t.set(Some(fut));
|
||||
this.fut_t.as_pin_mut().unwrap().poll(cx)
|
||||
} else {
|
||||
Poll::Pending
|
||||
Poll::Pending => Poll::Pending,
|
||||
},
|
||||
ApplyTransformFutureState::B(fut) => fut.poll(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,16 +64,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub struct TransformMapInitErrFuture<T, S, F, E>
|
||||
where
|
||||
#[pin_project::pin_project]
|
||||
pub struct TransformMapInitErrFuture<T, S, F, E>
|
||||
where
|
||||
T: Transform<S>,
|
||||
F: Fn(T::InitError) -> E,
|
||||
{
|
||||
{
|
||||
#[pin]
|
||||
fut: T::Future,
|
||||
f: F,
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S, F, E> Future for TransformMapInitErrFuture<T, S, F, E>
|
||||
|
@ -20,7 +20,7 @@ path = "src/lib.rs"
|
||||
actix-rt = "1.0.0-alpha.2"
|
||||
actix-macros = "0.1.0-alpha.1"
|
||||
actix-server = "1.0.0-alpha.2"
|
||||
actix-service = "1.0.0-alpha.2"
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
|
||||
log = "0.4"
|
||||
net2 = "0.2"
|
||||
|
@ -29,7 +29,7 @@ openssl = ["open-ssl", "tokio-openssl"]
|
||||
rustls = ["rust-tls", "webpki"]
|
||||
|
||||
[dependencies]
|
||||
actix-service = "1.0.0-alpha.2"
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
actix-codec = "0.2.0-alpha.2"
|
||||
actix-utils = "1.0.0-alpha.2"
|
||||
actix-rt = "1.0.0-alpha.2"
|
||||
|
@ -1,5 +1,7 @@
|
||||
# Changes
|
||||
|
||||
## [1.0.0-alpha.3] - 2019-12-xx
|
||||
|
||||
* Fix oneshot
|
||||
|
||||
## [1.0.0-alpha.2] - 2019-12-02
|
||||
|
@ -18,7 +18,7 @@ name = "actix_utils"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-service = "1.0.0-alpha.2"
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
actix-rt = "1.0.0-alpha.2"
|
||||
actix-codec = "0.2.0-alpha.2"
|
||||
bytes = "0.4"
|
||||
|
Loading…
Reference in New Issue
Block a user