Remove actix System from Accept thread

This commit is contained in:
fakeshadow 2021-04-21 21:30:38 +08:00
parent 8c983cf839
commit 4ff6323202
1 changed files with 63 additions and 58 deletions

View File

@ -1,10 +1,13 @@
use std::time::Duration; use std::{
use std::{io, thread}; future::Future,
io,
use actix_rt::{ pin::Pin,
time::{sleep, Instant, Sleep}, task::{Context, Poll},
System, thread,
time::Duration,
}; };
use actix_rt::time::{sleep, Instant, Sleep};
use log::error; use log::error;
use tokio::sync::mpsc::UnboundedReceiver; use tokio::sync::mpsc::UnboundedReceiver;
@ -25,10 +28,16 @@ pub(crate) struct Accept {
srv: Server, srv: Server,
next: usize, next: usize,
avail: Availability, avail: Availability,
paused: bool, state: AcceptState,
timeout: Pin<Box<Sleep>>, timeout: Pin<Box<Sleep>>,
} }
enum AcceptState {
Accept,
Pause,
Stop,
}
pub(crate) enum Interest { pub(crate) enum Interest {
Pause, Pause,
Resume, Resume,
@ -44,14 +53,10 @@ impl Accept {
srv: Server, srv: Server,
handles: Vec<WorkerHandleAccept>, handles: Vec<WorkerHandleAccept>,
) { ) {
// Accept runs in its own thread and would want to spawn additional futures to current // Accept runs in its own thread and tokio runtime
// actix system.
let sys = System::current();
thread::Builder::new() thread::Builder::new()
.name("actix-server accept loop".to_owned()) .name("actix-server accept loop".to_owned())
.spawn(move || { .spawn(move || {
System::set_current(sys);
tokio::runtime::Builder::new_current_thread() tokio::runtime::Builder::new_current_thread()
.enable_all() .enable_all()
.build() .build()
@ -87,11 +92,49 @@ impl Accept {
srv, srv,
next: 0, next: 0,
avail, avail,
paused: false, state: AcceptState::Accept,
timeout: Box::pin(sleep(Duration::from_millis(500))), timeout: Box::pin(sleep(Duration::from_millis(500))),
} }
} }
fn poll_accept(&mut self, cx: &mut Context<'_>) -> Poll<()> {
let len = self.sockets.len();
let mut idx = 0;
while idx < len {
'socket: loop {
if !self.avail.available() {
return Poll::Pending;
}
let socket = &mut self.sockets[idx];
match socket.lst.poll_accept(cx) {
Poll::Ready(Ok(io)) => {
let conn = Conn {
io,
token: socket.token,
};
self.accept_one(conn);
}
Poll::Ready(Err(ref e)) if connection_error(e) => continue 'socket,
Poll::Ready(Err(ref e)) => {
error!("Error accepting connection: {}", e);
let deadline = Instant::now() + Duration::from_millis(500);
self.timeout.as_mut().reset(deadline);
let _ = self.timeout.as_mut().poll(cx);
break 'socket;
}
Poll::Pending => break 'socket,
};
}
idx += 1;
}
Poll::Pending
}
// Send connection to worker and handle error. // Send connection to worker and handle error.
fn send_connection(&mut self, conn: Conn) -> Result<(), Conn> { fn send_connection(&mut self, conn: Conn) -> Result<(), Conn> {
let next = self.next(); let next = self.next();
@ -171,10 +214,6 @@ impl Accept {
} }
} }
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
impl Future for Accept { impl Future for Accept {
type Output = (); type Output = ();
@ -190,51 +229,17 @@ impl Future for Accept {
this.avail.set_available(handle.idx(), true); this.avail.set_available(handle.idx(), true);
this.handles.push(handle); this.handles.push(handle);
} }
Interest::Pause => this.paused = true, Interest::Pause => this.state = AcceptState::Pause,
Interest::Resume => this.paused = false, Interest::Resume => this.state = AcceptState::Accept,
Interest::Stop => return Poll::Ready(()), Interest::Stop => this.state = AcceptState::Stop,
} }
} }
if this.paused { match this.state {
return Poll::Pending; AcceptState::Accept => this.poll_accept(cx),
AcceptState::Pause => Poll::Pending,
AcceptState::Stop => Poll::Ready(()),
} }
let len = this.sockets.len();
let mut idx = 0;
while idx < len {
'socket: loop {
if !this.avail.available() {
return Poll::Pending;
}
let socket = &mut this.sockets[idx];
match socket.lst.poll_accept(cx) {
Poll::Ready(Ok(io)) => {
let conn = Conn {
io,
token: socket.token,
};
this.accept_one(conn);
}
Poll::Ready(Err(ref e)) if connection_error(e) => continue 'socket,
Poll::Ready(Err(ref e)) => {
error!("Error accepting connection: {}", e);
let deadline = Instant::now() + Duration::from_millis(500);
this.timeout.as_mut().reset(deadline);
let _ = this.timeout.as_mut().poll(cx);
break 'socket;
}
Poll::Pending => break 'socket,
};
}
idx += 1;
}
Poll::Pending
} }
} }