1
0
mirror of https://github.com/fafhrd91/actix-net synced 2024-12-19 12:12:37 +01:00
actix-net/actix-rt/src/system.rs

227 lines
6.3 KiB
Rust
Raw Normal View History

2021-01-26 10:46:14 +01:00
use std::{
cell::RefCell,
2021-01-29 05:08:14 +01:00
collections::HashMap,
future::Future,
2021-01-26 10:46:14 +01:00
io,
2021-01-29 05:08:14 +01:00
pin::Pin,
2021-01-26 10:46:14 +01:00
sync::atomic::{AtomicUsize, Ordering},
2021-01-29 05:08:14 +01:00
task::{Context, Poll},
2021-01-26 10:46:14 +01:00
};
2018-12-10 04:55:40 +01:00
2021-01-29 05:08:14 +01:00
use futures_core::ready;
use tokio::sync::{mpsc, oneshot};
2018-12-10 04:55:40 +01:00
use crate::{arbiter::ArbiterHandle, Arbiter, Runtime};
2018-12-10 04:55:40 +01:00
static SYSTEM_COUNT: AtomicUsize = AtomicUsize::new(0);
thread_local!(
static CURRENT: RefCell<Option<System>> = RefCell::new(None);
);
/// A manager for a per-thread distributed async runtime.
2018-12-10 04:55:40 +01:00
#[derive(Clone, Debug)]
pub struct System {
id: usize,
2021-01-29 16:16:30 +01:00
sys_tx: mpsc::UnboundedSender<SystemCommand>,
2018-12-10 04:55:40 +01:00
/// Handle to the first [Arbiter] that is created with the System.
arbiter_handle: ArbiterHandle,
}
2018-12-10 04:55:40 +01:00
impl System {
/// Create a new system.
///
/// # Panics
/// Panics if underlying Tokio runtime can not be created.
#[allow(clippy::new_ret_no_self)]
pub fn new() -> SystemRunner {
let (stop_tx, stop_rx) = oneshot::channel();
let (sys_tx, sys_rx) = mpsc::unbounded_channel();
let rt = Runtime::new().expect("Actix (Tokio) runtime could not be created.");
let system = System::construct(sys_tx, Arbiter::in_new_system(rt.local_set()));
// init background system arbiter
let sys_ctrl = SystemController::new(sys_rx, stop_tx);
rt.spawn(sys_ctrl);
SystemRunner {
rt,
stop_rx,
system,
}
}
/// Constructs new system and registers it on the current thread.
2021-01-29 16:16:30 +01:00
pub(crate) fn construct(
sys_tx: mpsc::UnboundedSender<SystemCommand>,
arbiter_handle: ArbiterHandle,
2021-01-29 16:16:30 +01:00
) -> Self {
2018-12-10 04:55:40 +01:00
let sys = System {
2021-01-29 16:16:30 +01:00
sys_tx,
arbiter_handle,
id: SYSTEM_COUNT.fetch_add(1, Ordering::SeqCst),
2018-12-10 04:55:40 +01:00
};
System::set_current(sys.clone());
2018-12-10 04:55:40 +01:00
sys
2018-12-10 04:55:40 +01:00
}
/// Get current running system.
2021-01-29 16:16:30 +01:00
///
/// # Panics
/// Panics if no system is registered on the current thread.
2018-12-10 04:55:40 +01:00
pub fn current() -> System {
CURRENT.with(|cell| match *cell.borrow() {
Some(ref sys) => sys.clone(),
None => panic!("System is not running"),
})
}
/// Get handle to a the System's initial [Arbiter].
pub fn arbiter(&self) -> &ArbiterHandle {
&self.arbiter_handle
2018-12-10 04:55:40 +01:00
}
/// Check if there is a System registered on the current thread.
pub fn is_registered() -> bool {
CURRENT.with(|sys| sys.borrow().is_some())
2018-12-10 04:55:40 +01:00
}
/// Register given system on current thread.
#[doc(hidden)]
pub fn set_current(sys: System) {
CURRENT.with(|cell| {
*cell.borrow_mut() = Some(sys);
2018-12-10 04:55:40 +01:00
})
}
/// Numeric system identifier.
///
/// Useful when using multiple Systems.
pub fn id(&self) -> usize {
self.id
}
2021-01-26 10:46:14 +01:00
/// Stop the system (with code 0).
2018-12-10 04:55:40 +01:00
pub fn stop(&self) {
self.stop_with_code(0)
}
/// Stop the system with a given exit code.
2018-12-10 04:55:40 +01:00
pub fn stop_with_code(&self, code: i32) {
2021-01-29 16:16:30 +01:00
let _ = self.sys_tx.send(SystemCommand::Exit(code));
2018-12-10 04:55:40 +01:00
}
2021-01-29 05:08:14 +01:00
pub(crate) fn tx(&self) -> &mpsc::UnboundedSender<SystemCommand> {
2021-01-29 16:16:30 +01:00
&self.sys_tx
2018-12-10 04:55:40 +01:00
}
}
2018-12-10 04:55:40 +01:00
/// Runner that keeps a [System]'s event loop alive until stop message is received.
#[must_use = "A SystemRunner does nothing unless `run` is called."]
#[derive(Debug)]
pub struct SystemRunner {
rt: Runtime,
stop_rx: oneshot::Receiver<i32>,
system: System,
}
impl SystemRunner {
/// Starts event loop and will return once [System] is [stopped](System::stop).
pub fn run(self) -> io::Result<()> {
let SystemRunner { rt, stop_rx, .. } = self;
// run loop
match rt.block_on(stop_rx) {
Ok(code) => {
if code != 0 {
Err(io::Error::new(
io::ErrorKind::Other,
format!("Non-zero exit code: {}", code),
))
} else {
Ok(())
}
}
Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
}
2018-12-10 04:55:40 +01:00
}
/// Runs the provided future, blocking the current thread until the future completes.
#[inline]
pub fn block_on<F: Future>(&self, fut: F) -> F::Output {
self.rt.block_on(fut)
2018-12-10 04:55:40 +01:00
}
}
2021-01-29 05:08:14 +01:00
#[derive(Debug)]
pub(crate) enum SystemCommand {
Exit(i32),
RegisterArbiter(usize, ArbiterHandle),
2021-01-29 05:08:14 +01:00
DeregisterArbiter(usize),
}
/// There is one `SystemController` per [System]. It runs in the background, keeping track of
/// [Arbiter]s and is able to distribute a system-wide stop command.
2021-01-29 05:08:14 +01:00
#[derive(Debug)]
pub(crate) struct SystemController {
stop_tx: Option<oneshot::Sender<i32>>,
cmd_rx: mpsc::UnboundedReceiver<SystemCommand>,
arbiters: HashMap<usize, ArbiterHandle>,
2021-01-29 05:08:14 +01:00
}
impl SystemController {
2021-01-29 05:08:14 +01:00
pub(crate) fn new(
cmd_rx: mpsc::UnboundedReceiver<SystemCommand>,
stop_tx: oneshot::Sender<i32>,
2021-01-29 05:08:14 +01:00
) -> Self {
SystemController {
cmd_rx,
stop_tx: Some(stop_tx),
arbiters: HashMap::with_capacity(4),
2021-01-29 05:08:14 +01:00
}
}
}
impl Future for SystemController {
2021-01-29 05:08:14 +01:00
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// process all items currently buffered in channel
loop {
match ready!(Pin::new(&mut self.cmd_rx).poll_recv(cx)) {
2021-01-29 05:08:14 +01:00
// channel closed; no more messages can be received
None => return Poll::Ready(()),
// process system command
Some(cmd) => match cmd {
SystemCommand::Exit(code) => {
// stop all arbiters
for wkr in self.arbiters.values() {
2021-01-29 16:16:30 +01:00
wkr.stop();
2021-01-29 05:08:14 +01:00
}
2021-01-29 16:16:30 +01:00
2021-01-29 05:08:14 +01:00
// stop event loop
// will only fire once
if let Some(stop_tx) = self.stop_tx.take() {
let _ = stop_tx.send(code);
2021-01-29 05:08:14 +01:00
}
}
2021-01-29 16:16:30 +01:00
2021-01-29 05:08:14 +01:00
SystemCommand::RegisterArbiter(name, hnd) => {
self.arbiters.insert(name, hnd);
2021-01-29 05:08:14 +01:00
}
2021-01-29 16:16:30 +01:00
2021-01-29 05:08:14 +01:00
SystemCommand::DeregisterArbiter(name) => {
self.arbiters.remove(&name);
2021-01-29 05:08:14 +01:00
}
},
}
}
}
}