mirror of
https://github.com/fafhrd91/actix-net
synced 2024-11-27 23:42:56 +01:00
Merge pull request #22 from GeorgeHahn/with-external-runtime
Allow Actix to be started on an external CurrentThread runtime
This commit is contained in:
commit
1c04ad3238
@ -1,11 +1,12 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
|
use futures::future;
|
||||||
use futures::future::{lazy, Future};
|
use futures::future::{lazy, Future};
|
||||||
use futures::sync::mpsc::unbounded;
|
use futures::sync::mpsc::unbounded;
|
||||||
use futures::sync::oneshot::{channel, Receiver};
|
use futures::sync::oneshot::{channel, Receiver};
|
||||||
|
|
||||||
use tokio_current_thread::CurrentThread;
|
use tokio_current_thread::{CurrentThread, Handle};
|
||||||
use tokio_reactor::Reactor;
|
use tokio_reactor::Reactor;
|
||||||
use tokio_timer::clock::Clock;
|
use tokio_timer::clock::Clock;
|
||||||
use tokio_timer::timer::Timer;
|
use tokio_timer::timer::Timer;
|
||||||
@ -69,6 +70,13 @@ impl Builder {
|
|||||||
self.create_runtime(|| {})
|
self.create_runtime(|| {})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create new System that can run asynchronously.
|
||||||
|
///
|
||||||
|
/// This method panics if it cannot start the system arbiter
|
||||||
|
pub(crate) fn build_async(self, executor: Handle) -> AsyncSystemRunner {
|
||||||
|
self.create_async_runtime(executor)
|
||||||
|
}
|
||||||
|
|
||||||
/// This function will start tokio runtime and will finish once the
|
/// This function will start tokio runtime and will finish once the
|
||||||
/// `System::stop()` message get called.
|
/// `System::stop()` message get called.
|
||||||
/// Function `f` get called within tokio runtime context.
|
/// Function `f` get called within tokio runtime context.
|
||||||
@ -79,6 +87,21 @@ impl Builder {
|
|||||||
self.create_runtime(f).run()
|
self.create_runtime(f).run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_async_runtime(self, executor: Handle) -> AsyncSystemRunner {
|
||||||
|
let (stop_tx, stop) = channel();
|
||||||
|
let (sys_sender, sys_receiver) = unbounded();
|
||||||
|
|
||||||
|
let system = System::construct(sys_sender, Arbiter::new_system(), self.stop_on_panic);
|
||||||
|
|
||||||
|
// system arbiter
|
||||||
|
let arb = SystemArbiter::new(stop_tx, sys_receiver);
|
||||||
|
|
||||||
|
// start the system arbiter
|
||||||
|
executor.spawn(arb).expect("could not start system arbiter");
|
||||||
|
|
||||||
|
AsyncSystemRunner { stop, system }
|
||||||
|
}
|
||||||
|
|
||||||
fn create_runtime<F>(self, f: F) -> SystemRunner
|
fn create_runtime<F>(self, f: F) -> SystemRunner
|
||||||
where
|
where
|
||||||
F: FnOnce() + 'static,
|
F: FnOnce() + 'static,
|
||||||
@ -127,6 +150,42 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct AsyncSystemRunner {
|
||||||
|
stop: Receiver<i32>,
|
||||||
|
system: System,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsyncSystemRunner {
|
||||||
|
/// This function will start event loop and returns a future that
|
||||||
|
/// resolves once the `System::stop()` function is called.
|
||||||
|
pub(crate) fn run_nonblocking(self) -> Box<Future<Item = (), Error = io::Error> + Send + 'static> {
|
||||||
|
let AsyncSystemRunner { stop, .. } = self;
|
||||||
|
|
||||||
|
// run loop
|
||||||
|
Box::new(future::lazy(|| {
|
||||||
|
Arbiter::run_system();
|
||||||
|
stop.then(|res| match res {
|
||||||
|
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)),
|
||||||
|
})
|
||||||
|
.then(|result| {
|
||||||
|
Arbiter::stop_system();
|
||||||
|
result
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper object that runs System's event loop
|
/// Helper object that runs System's event loop
|
||||||
#[must_use = "SystemRunner must be run"]
|
#[must_use = "SystemRunner must be run"]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -3,9 +3,11 @@ use std::io;
|
|||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
use futures::sync::mpsc::UnboundedSender;
|
use futures::sync::mpsc::UnboundedSender;
|
||||||
|
use futures::Future;
|
||||||
|
use tokio_current_thread::Handle;
|
||||||
|
|
||||||
use crate::arbiter::{Arbiter, SystemCommand};
|
use crate::arbiter::{Arbiter, SystemCommand};
|
||||||
use crate::builder::{Builder, SystemRunner};
|
use crate::builder::{AsyncSystemRunner, Builder, SystemRunner};
|
||||||
|
|
||||||
static SYSTEM_COUNT: AtomicUsize = AtomicUsize::new(0);
|
static SYSTEM_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
@ -55,6 +57,20 @@ impl System {
|
|||||||
Self::builder().name(name).build()
|
Self::builder().name(name).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::new_ret_no_self)]
|
||||||
|
/// Create new system using provided CurrentThread Handle.
|
||||||
|
///
|
||||||
|
/// This method panics if it can not spawn system arbiter
|
||||||
|
pub fn run_in_executor<T: Into<String>>(
|
||||||
|
name: T,
|
||||||
|
executor: Handle,
|
||||||
|
) -> Box<Future<Item = (), Error = io::Error> + Send + 'static> {
|
||||||
|
Self::builder()
|
||||||
|
.name(name)
|
||||||
|
.build_async(executor)
|
||||||
|
.run_nonblocking()
|
||||||
|
}
|
||||||
|
|
||||||
/// Get current running system.
|
/// Get current running system.
|
||||||
pub fn current() -> System {
|
pub fn current() -> System {
|
||||||
CURRENT.with(|cell| match *cell.borrow() {
|
CURRENT.with(|cell| match *cell.borrow() {
|
||||||
|
Loading…
Reference in New Issue
Block a user