mirror of https://github.com/fafhrd91/actix-net
Merge branch 'master' into feat/reuse_box_future
This commit is contained in:
commit
13b01baa7b
|
@ -6,7 +6,7 @@ description = "Codec utilities for working with framed protocols"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
documentation = "https://docs.rs/actix-codec/"
|
documentation = "https://docs.rs/actix-codec"
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
|
@ -3,8 +3,16 @@
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
|
||||||
|
|
||||||
|
## 0.2.0 - 2021-02-02
|
||||||
|
* Update to latest `actix_rt::System::new` signature. [#261]
|
||||||
|
|
||||||
|
[#261]: https://github.com/actix/actix-net/pull/261
|
||||||
|
|
||||||
|
|
||||||
## 0.2.0-beta.1 - 2021-01-09
|
## 0.2.0-beta.1 - 2021-01-09
|
||||||
* Remove `actix-reexport` feature.
|
* Remove `actix-reexport` feature. [#218]
|
||||||
|
|
||||||
|
[#218]: https://github.com/actix/actix-net/pull/218
|
||||||
|
|
||||||
|
|
||||||
## 0.1.3 - 2020-12-03
|
## 0.1.3 - 2020-12-03
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-macros"
|
name = "actix-macros"
|
||||||
version = "0.2.0-beta.1"
|
version = "0.2.0"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix runtime macros"
|
description = "Macros for Actix system and runtime"
|
||||||
repository = "https://github.com/actix/actix-net"
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
documentation = "https://docs.rs/actix-macros/"
|
documentation = "https://docs.rs/actix-macros"
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
@ -16,11 +16,8 @@ proc-macro = true
|
||||||
quote = "1.0.3"
|
quote = "1.0.3"
|
||||||
syn = { version = "^1", features = ["full"] }
|
syn = { version = "^1", features = ["full"] }
|
||||||
|
|
||||||
[features]
|
|
||||||
actix-reexport = []
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "2.0.0-beta.2"
|
actix-rt = "2.0.0-beta.3"
|
||||||
|
|
||||||
futures-util = { version = "0.3", default-features = false }
|
futures-util = { version = "0.3", default-features = false }
|
||||||
trybuild = "1"
|
trybuild = "1"
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
//! Macros for use with Tokio
|
//! Macros for Actix system and runtime.
|
||||||
|
//!
|
||||||
|
//! The [`actix-rt`](https://docs.rs/actix-rt) crate must be available for macro output to compile.
|
||||||
|
//!
|
||||||
|
//! # Entry-point
|
||||||
|
//! See docs for the [`#[main]`](macro@main) macro.
|
||||||
|
//!
|
||||||
|
//! # Tests
|
||||||
|
//! See docs for the [`#[test]`](macro@test) macro.
|
||||||
|
|
||||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||||
|
@ -7,10 +15,9 @@
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
/// Marks async function to be executed by Actix system.
|
/// Marks async entry-point function to be executed by Actix system.
|
||||||
///
|
|
||||||
/// ## Usage
|
|
||||||
///
|
///
|
||||||
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// #[actix_rt::main]
|
/// #[actix_rt::main]
|
||||||
/// async fn main() {
|
/// async fn main() {
|
||||||
|
@ -28,7 +35,10 @@ pub fn main(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
let body = &input.block;
|
let body = &input.block;
|
||||||
|
|
||||||
if sig.asyncness.is_none() {
|
if sig.asyncness.is_none() {
|
||||||
return syn::Error::new_spanned(sig.fn_token, "only async fn is supported")
|
return syn::Error::new_spanned(
|
||||||
|
sig.fn_token,
|
||||||
|
"the async keyword is missing from the function declaration",
|
||||||
|
)
|
||||||
.to_compile_error()
|
.to_compile_error()
|
||||||
.into();
|
.into();
|
||||||
}
|
}
|
||||||
|
@ -45,11 +55,10 @@ pub fn main(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Marks async test function to be executed by Actix system.
|
/// Marks async test function to be executed in an Actix system.
|
||||||
///
|
///
|
||||||
/// ## Usage
|
/// # Examples
|
||||||
///
|
/// ```
|
||||||
/// ```no_run
|
|
||||||
/// #[actix_rt::test]
|
/// #[actix_rt::test]
|
||||||
/// async fn my_test() {
|
/// async fn my_test() {
|
||||||
/// assert!(true);
|
/// assert!(true);
|
||||||
|
@ -73,7 +82,7 @@ pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
if sig.asyncness.is_none() {
|
if sig.asyncness.is_none() {
|
||||||
return syn::Error::new_spanned(
|
return syn::Error::new_spanned(
|
||||||
input.sig.fn_token,
|
input.sig.fn_token,
|
||||||
format!("only async fn is supported, {}", input.sig.ident),
|
"the async keyword is missing from the function declaration",
|
||||||
)
|
)
|
||||||
.to_compile_error()
|
.to_compile_error()
|
||||||
.into();
|
.into();
|
||||||
|
@ -81,24 +90,19 @@ pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
sig.asyncness = None;
|
sig.asyncness = None;
|
||||||
|
|
||||||
let result = if has_test_attr {
|
let missing_test_attr = if has_test_attr {
|
||||||
quote! {
|
quote!()
|
||||||
#(#attrs)*
|
|
||||||
#vis #sig {
|
|
||||||
actix_rt::System::new()
|
|
||||||
.block_on(async { #body })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
quote! {
|
quote!(#[test])
|
||||||
#[test]
|
|
||||||
#(#attrs)*
|
|
||||||
#vis #sig {
|
|
||||||
actix_rt::System::new()
|
|
||||||
.block_on(async { #body })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
result.into()
|
(quote! {
|
||||||
|
#missing_test_attr
|
||||||
|
#(#attrs)*
|
||||||
|
#vis #sig {
|
||||||
|
actix_rt::System::new()
|
||||||
|
.block_on(async { #body })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,9 @@ fn compile_macros() {
|
||||||
let t = trybuild::TestCases::new();
|
let t = trybuild::TestCases::new();
|
||||||
t.pass("tests/trybuild/main-01-basic.rs");
|
t.pass("tests/trybuild/main-01-basic.rs");
|
||||||
t.compile_fail("tests/trybuild/main-02-only-async.rs");
|
t.compile_fail("tests/trybuild/main-02-only-async.rs");
|
||||||
|
t.pass("tests/trybuild/main-03-fn-params.rs");
|
||||||
|
|
||||||
t.pass("tests/trybuild/test-01-basic.rs");
|
t.pass("tests/trybuild/test-01-basic.rs");
|
||||||
t.pass("tests/trybuild/test-02-keep-attrs.rs");
|
t.pass("tests/trybuild/test-02-keep-attrs.rs");
|
||||||
|
t.compile_fail("tests/trybuild/test-03-only-async.rs");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: only async fn is supported
|
error: the async keyword is missing from the function declaration
|
||||||
--> $DIR/main-02-only-async.rs:2:1
|
--> $DIR/main-02-only-async.rs:2:1
|
||||||
|
|
|
|
||||||
2 | fn main() {
|
2 | fn main() {
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
#[actix_rt::main]
|
||||||
|
async fn main2(_param: bool) {
|
||||||
|
futures_util::future::ready(()).await
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#[actix_rt::test]
|
||||||
|
fn my_test() {
|
||||||
|
futures_util::future::ready(()).await
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,5 @@
|
||||||
|
error: the async keyword is missing from the function declaration
|
||||||
|
--> $DIR/test-03-only-async.rs:2:1
|
||||||
|
|
|
||||||
|
2 | fn my_test() {
|
||||||
|
| ^^
|
|
@ -6,7 +6,7 @@ description = "Resource path matching library"
|
||||||
keywords = ["actix"]
|
keywords = ["actix"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
documentation = "https://docs.rs/actix-router/"
|
documentation = "https://docs.rs/actix-router"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ enum PatternElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
enum PatternType {
|
enum PatternType {
|
||||||
Static(String),
|
Static(String),
|
||||||
Prefix(String),
|
Prefix(String),
|
||||||
|
|
|
@ -3,6 +3,13 @@
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
|
||||||
|
|
||||||
|
## 2.0.0 - 2021-02-02
|
||||||
|
* Remove all Arbiter-local storage methods. [#262]
|
||||||
|
* Re-export `tokio::pin`. [#262]
|
||||||
|
|
||||||
|
[#262]: https://github.com/actix/actix-net/pull/262
|
||||||
|
|
||||||
|
|
||||||
## 2.0.0-beta.3 - 2021-01-31
|
## 2.0.0-beta.3 - 2021-01-31
|
||||||
* Remove `run_in_tokio`, `attach_to_tokio` and `AsyncSystemRunner`. [#253]
|
* Remove `run_in_tokio`, `attach_to_tokio` and `AsyncSystemRunner`. [#253]
|
||||||
* Return `JoinHandle` from `actix_rt::spawn`. [#253]
|
* Return `JoinHandle` from `actix_rt::spawn`. [#253]
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-rt"
|
name = "actix-rt"
|
||||||
version = "2.0.0-beta.3"
|
version = "2.0.0"
|
||||||
authors = [
|
authors = [
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
"Rob Ede <robjtede@icloud.com>",
|
||||||
]
|
]
|
||||||
description = "Tokio-based single-thread async runtime for the Actix ecosystem"
|
description = "Tokio-based single-threaded async runtime for the Actix ecosystem"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["async", "futures", "io", "runtime"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
documentation = "https://docs.rs/actix-rt/"
|
documentation = "https://docs.rs/actix-rt"
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
@ -23,10 +23,11 @@ default = ["macros"]
|
||||||
macros = ["actix-macros"]
|
macros = ["actix-macros"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-macros = { version = "0.2.0-beta.1", optional = true }
|
actix-macros = { version = "0.2.0", optional = true }
|
||||||
|
|
||||||
futures-core = { version = "0.3", default-features = false }
|
futures-core = { version = "0.3", default-features = false }
|
||||||
tokio = { version = "1", features = ["rt", "net", "parking_lot", "signal", "sync", "time"] }
|
tokio = { version = "1", features = ["rt", "net", "parking_lot", "signal", "sync", "time"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
hyper = { version = "0.14", default-features = false, features = ["server", "tcp", "http1"] }
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
# actix-rt
|
# actix-rt
|
||||||
|
|
||||||
> Tokio-based single-thread async runtime for the Actix ecosystem.
|
> Tokio-based single-threaded async runtime for the Actix ecosystem.
|
||||||
|
|
||||||
See documentation for detailed explanations these components: [https://docs.rs/actix-rt][docs].
|
See crate documentation for more: https://docs.rs/actix-rt.
|
||||||
|
|
||||||
[docs]: https://docs.rs/actix-rt
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
use hyper::service::{make_service_fn, service_fn};
|
||||||
|
use hyper::{Body, Request, Response, Server};
|
||||||
|
use std::convert::Infallible;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
||||||
|
Ok(Response::new(Body::from("Hello World")))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
actix_rt::System::with_tokio_rt(|| {
|
||||||
|
tokio::runtime::Builder::new_multi_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.block_on(async {
|
||||||
|
let make_service =
|
||||||
|
make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(handle)) });
|
||||||
|
|
||||||
|
let server =
|
||||||
|
Server::bind(&SocketAddr::from(([127, 0, 0, 1], 3000))).serve(make_service);
|
||||||
|
|
||||||
|
if let Err(e) = server.await {
|
||||||
|
eprintln!("server error: {}", e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,7 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::HashMap,
|
|
||||||
fmt,
|
fmt,
|
||||||
future::Future,
|
future::Future,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
|
@ -14,7 +12,7 @@ use futures_core::ready;
|
||||||
use tokio::{sync::mpsc, task::LocalSet};
|
use tokio::{sync::mpsc, task::LocalSet};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
runtime::Runtime,
|
runtime::{default_tokio_runtime, Runtime},
|
||||||
system::{System, SystemCommand},
|
system::{System, SystemCommand},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,7 +20,6 @@ pub(crate) static COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
thread_local!(
|
thread_local!(
|
||||||
static HANDLE: RefCell<Option<ArbiterHandle>> = RefCell::new(None);
|
static HANDLE: RefCell<Option<ArbiterHandle>> = RefCell::new(None);
|
||||||
static STORAGE: RefCell<HashMap<TypeId, Box<dyn Any>>> = RefCell::new(HashMap::new());
|
|
||||||
);
|
);
|
||||||
|
|
||||||
pub(crate) enum ArbiterCommand {
|
pub(crate) enum ArbiterCommand {
|
||||||
|
@ -97,16 +94,30 @@ pub struct Arbiter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Arbiter {
|
impl Arbiter {
|
||||||
/// Spawn new Arbiter thread and start its event loop.
|
/// Spawn a new Arbiter thread and start its event loop.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
/// Panics if a [System] is not registered on the current thread.
|
/// Panics if a [System] is not registered on the current thread.
|
||||||
#[allow(clippy::new_without_default)]
|
#[allow(clippy::new_without_default)]
|
||||||
pub fn new() -> Arbiter {
|
pub fn new() -> Arbiter {
|
||||||
let id = COUNT.fetch_add(1, Ordering::Relaxed);
|
Self::with_tokio_rt(|| {
|
||||||
let system_id = System::current().id();
|
default_tokio_runtime().expect("Cannot create new Arbiter's Runtime.")
|
||||||
let name = format!("actix-rt|system:{}|arbiter:{}", system_id, id);
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Spawn a new Arbiter using the [Tokio Runtime](tokio-runtime) returned from a closure.
|
||||||
|
///
|
||||||
|
/// [tokio-runtime]: tokio::runtime::Runtime
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn with_tokio_rt<F>(runtime_factory: F) -> Arbiter
|
||||||
|
where
|
||||||
|
F: Fn() -> tokio::runtime::Runtime + Send + 'static,
|
||||||
|
{
|
||||||
let sys = System::current();
|
let sys = System::current();
|
||||||
|
let system_id = sys.id();
|
||||||
|
let arb_id = COUNT.fetch_add(1, Ordering::Relaxed);
|
||||||
|
|
||||||
|
let name = format!("actix-rt|system:{}|arbiter:{}", system_id, arb_id);
|
||||||
let (tx, rx) = mpsc::unbounded_channel();
|
let (tx, rx) = mpsc::unbounded_channel();
|
||||||
|
|
||||||
let (ready_tx, ready_rx) = std::sync::mpsc::channel::<()>();
|
let (ready_tx, ready_rx) = std::sync::mpsc::channel::<()>();
|
||||||
|
@ -116,18 +127,17 @@ impl Arbiter {
|
||||||
.spawn({
|
.spawn({
|
||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
move || {
|
move || {
|
||||||
let rt = Runtime::new().expect("Cannot create new Arbiter's Runtime.");
|
let rt = Runtime::from(runtime_factory());
|
||||||
let hnd = ArbiterHandle::new(tx);
|
let hnd = ArbiterHandle::new(tx);
|
||||||
|
|
||||||
System::set_current(sys);
|
System::set_current(sys);
|
||||||
|
|
||||||
STORAGE.with(|cell| cell.borrow_mut().clear());
|
|
||||||
HANDLE.with(|cell| *cell.borrow_mut() = Some(hnd.clone()));
|
HANDLE.with(|cell| *cell.borrow_mut() = Some(hnd.clone()));
|
||||||
|
|
||||||
// register arbiter
|
// register arbiter
|
||||||
let _ = System::current()
|
let _ = System::current()
|
||||||
.tx()
|
.tx()
|
||||||
.send(SystemCommand::RegisterArbiter(id, hnd));
|
.send(SystemCommand::RegisterArbiter(arb_id, hnd));
|
||||||
|
|
||||||
ready_tx.send(()).unwrap();
|
ready_tx.send(()).unwrap();
|
||||||
|
|
||||||
|
@ -137,7 +147,7 @@ impl Arbiter {
|
||||||
// deregister arbiter
|
// deregister arbiter
|
||||||
let _ = System::current()
|
let _ = System::current()
|
||||||
.tx()
|
.tx()
|
||||||
.send(SystemCommand::DeregisterArbiter(id));
|
.send(SystemCommand::DeregisterArbiter(arb_id));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
|
@ -156,7 +166,6 @@ impl Arbiter {
|
||||||
let hnd = ArbiterHandle::new(tx);
|
let hnd = ArbiterHandle::new(tx);
|
||||||
|
|
||||||
HANDLE.with(|cell| *cell.borrow_mut() = Some(hnd.clone()));
|
HANDLE.with(|cell| *cell.borrow_mut() = Some(hnd.clone()));
|
||||||
STORAGE.with(|cell| cell.borrow_mut().clear());
|
|
||||||
|
|
||||||
local.spawn_local(ArbiterRunner { rx });
|
local.spawn_local(ArbiterRunner { rx });
|
||||||
|
|
||||||
|
@ -214,58 +223,6 @@ impl Arbiter {
|
||||||
pub fn join(self) -> thread::Result<()> {
|
pub fn join(self) -> thread::Result<()> {
|
||||||
self.thread_handle.join()
|
self.thread_handle.join()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert item into Arbiter's thread-local storage.
|
|
||||||
///
|
|
||||||
/// Overwrites any item of the same type previously inserted.
|
|
||||||
#[deprecated = "Will be removed in stable v2."]
|
|
||||||
pub fn set_item<T: 'static>(item: T) {
|
|
||||||
STORAGE.with(move |cell| cell.borrow_mut().insert(TypeId::of::<T>(), Box::new(item)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if Arbiter's thread-local storage contains an item type.
|
|
||||||
#[deprecated = "Will be removed in stable v2."]
|
|
||||||
pub fn contains_item<T: 'static>() -> bool {
|
|
||||||
STORAGE.with(move |cell| cell.borrow().contains_key(&TypeId::of::<T>()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Call a function with a shared reference to an item in this Arbiter's thread-local storage.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
/// Panics if item is not in Arbiter's thread-local item storage.
|
|
||||||
#[deprecated = "Will be removed in stable v2."]
|
|
||||||
pub fn get_item<T: 'static, F, R>(mut f: F) -> R
|
|
||||||
where
|
|
||||||
F: FnMut(&T) -> R,
|
|
||||||
{
|
|
||||||
STORAGE.with(move |cell| {
|
|
||||||
let st = cell.borrow();
|
|
||||||
|
|
||||||
let type_id = TypeId::of::<T>();
|
|
||||||
let item = st.get(&type_id).and_then(downcast_ref).unwrap();
|
|
||||||
|
|
||||||
f(item)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Call a function with a mutable reference to an item in this Arbiter's thread-local storage.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
/// Panics if item is not in Arbiter's thread-local item storage.
|
|
||||||
#[deprecated = "Will be removed in stable v2."]
|
|
||||||
pub fn get_mut_item<T: 'static, F, R>(mut f: F) -> R
|
|
||||||
where
|
|
||||||
F: FnMut(&mut T) -> R,
|
|
||||||
{
|
|
||||||
STORAGE.with(move |cell| {
|
|
||||||
let mut st = cell.borrow_mut();
|
|
||||||
|
|
||||||
let type_id = TypeId::of::<T>();
|
|
||||||
let item = st.get_mut(&type_id).and_then(downcast_mut).unwrap();
|
|
||||||
|
|
||||||
f(item)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A persistent future that processes [Arbiter] commands.
|
/// A persistent future that processes [Arbiter] commands.
|
||||||
|
@ -296,11 +253,3 @@ impl Future for ArbiterRunner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn downcast_ref<T: 'static>(boxed: &Box<dyn Any>) -> Option<&T> {
|
|
||||||
boxed.downcast_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn downcast_mut<T: 'static>(boxed: &mut Box<dyn Any>) -> Option<&mut T> {
|
|
||||||
boxed.downcast_mut()
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Tokio-based single-thread async runtime for the Actix ecosystem.
|
//! Tokio-based single-threaded async runtime for the Actix ecosystem.
|
||||||
//!
|
//!
|
||||||
//! In most parts of the the Actix ecosystem, it has been chosen to use !Send futures. For this
|
//! In most parts of the the Actix ecosystem, it has been chosen to use !Send futures. For this
|
||||||
//! reason, a single-threaded runtime is appropriate since it is guaranteed that futures will not
|
//! reason, a single-threaded runtime is appropriate since it is guaranteed that futures will not
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
//!
|
//!
|
||||||
//! The disadvantage is that idle threads will not steal work from very busy, stuck or otherwise
|
//! The disadvantage is that idle threads will not steal work from very busy, stuck or otherwise
|
||||||
//! backlogged threads. Tasks that are disproportionately expensive should be offloaded to the
|
//! backlogged threads. Tasks that are disproportionately expensive should be offloaded to the
|
||||||
//! blocking thread-pool using [`task::spawn_blocking`].
|
//! blocking task thread-pool using [`task::spawn_blocking`].
|
||||||
//!
|
//!
|
||||||
//! # Examples
|
//! # Examples
|
||||||
//! ```
|
//! ```
|
||||||
|
@ -56,6 +56,8 @@ pub use self::arbiter::{Arbiter, ArbiterHandle};
|
||||||
pub use self::runtime::Runtime;
|
pub use self::runtime::Runtime;
|
||||||
pub use self::system::{System, SystemRunner};
|
pub use self::system::{System, SystemRunner};
|
||||||
|
|
||||||
|
pub use tokio::pin;
|
||||||
|
|
||||||
pub mod signal {
|
pub mod signal {
|
||||||
//! Asynchronous signal handling (Tokio re-exports).
|
//! Asynchronous signal handling (Tokio re-exports).
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::{future::Future, io};
|
||||||
|
|
||||||
use tokio::task::{JoinHandle, LocalSet};
|
use tokio::task::{JoinHandle, LocalSet};
|
||||||
|
|
||||||
/// A single-threaded runtime based on Tokio's "current thread" runtime.
|
/// A Tokio-based runtime proxy.
|
||||||
///
|
///
|
||||||
/// All spawned futures will be executed on the current thread. Therefore, there is no `Send` bound
|
/// All spawned futures will be executed on the current thread. Therefore, there is no `Send` bound
|
||||||
/// on submitted futures.
|
/// on submitted futures.
|
||||||
|
@ -12,14 +12,18 @@ pub struct Runtime {
|
||||||
rt: tokio::runtime::Runtime,
|
rt: tokio::runtime::Runtime,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn default_tokio_runtime() -> io::Result<tokio::runtime::Runtime> {
|
||||||
|
tokio::runtime::Builder::new_current_thread()
|
||||||
|
.enable_io()
|
||||||
|
.enable_time()
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
impl Runtime {
|
impl Runtime {
|
||||||
/// Returns a new runtime initialized with default configuration values.
|
/// Returns a new runtime initialized with default configuration values.
|
||||||
#[allow(clippy::new_ret_no_self)]
|
#[allow(clippy::new_ret_no_self)]
|
||||||
pub fn new() -> io::Result<Runtime> {
|
pub fn new() -> io::Result<Self> {
|
||||||
let rt = tokio::runtime::Builder::new_current_thread()
|
let rt = default_tokio_runtime()?;
|
||||||
.enable_io()
|
|
||||||
.enable_time()
|
|
||||||
.build()?;
|
|
||||||
|
|
||||||
Ok(Runtime {
|
Ok(Runtime {
|
||||||
rt,
|
rt,
|
||||||
|
@ -81,3 +85,12 @@ impl Runtime {
|
||||||
self.local.block_on(&self.rt, f)
|
self.local.block_on(&self.rt, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<tokio::runtime::Runtime> for Runtime {
|
||||||
|
fn from(rt: tokio::runtime::Runtime) -> Self {
|
||||||
|
Self {
|
||||||
|
local: LocalSet::new(),
|
||||||
|
rt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use std::{
|
||||||
use futures_core::ready;
|
use futures_core::ready;
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
|
||||||
use crate::{arbiter::ArbiterHandle, Arbiter, Runtime};
|
use crate::{arbiter::ArbiterHandle, runtime::default_tokio_runtime, Arbiter, Runtime};
|
||||||
|
|
||||||
static SYSTEM_COUNT: AtomicUsize = AtomicUsize::new(0);
|
static SYSTEM_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
|
@ -36,10 +36,24 @@ impl System {
|
||||||
/// Panics if underlying Tokio runtime can not be created.
|
/// Panics if underlying Tokio runtime can not be created.
|
||||||
#[allow(clippy::new_ret_no_self)]
|
#[allow(clippy::new_ret_no_self)]
|
||||||
pub fn new() -> SystemRunner {
|
pub fn new() -> SystemRunner {
|
||||||
|
Self::with_tokio_rt(|| {
|
||||||
|
default_tokio_runtime()
|
||||||
|
.expect("Default Actix (Tokio) runtime could not be created.")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new System using the [Tokio Runtime](tokio-runtime) returned from a closure.
|
||||||
|
///
|
||||||
|
/// [tokio-runtime]: tokio::runtime::Runtime
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn with_tokio_rt<F>(runtime_factory: F) -> SystemRunner
|
||||||
|
where
|
||||||
|
F: Fn() -> tokio::runtime::Runtime,
|
||||||
|
{
|
||||||
let (stop_tx, stop_rx) = oneshot::channel();
|
let (stop_tx, stop_rx) = oneshot::channel();
|
||||||
let (sys_tx, sys_rx) = mpsc::unbounded_channel();
|
let (sys_tx, sys_rx) = mpsc::unbounded_channel();
|
||||||
|
|
||||||
let rt = Runtime::new().expect("Actix (Tokio) runtime could not be created.");
|
let rt = Runtime::from(runtime_factory());
|
||||||
let sys_arbiter = Arbiter::in_new_system(rt.local_set());
|
let sys_arbiter = Arbiter::in_new_system(rt.local_set());
|
||||||
let system = System::construct(sys_tx, sys_arbiter.clone());
|
let system = System::construct(sys_tx, sys_arbiter.clone());
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
use std::{
|
use std::{
|
||||||
sync::mpsc::channel,
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
mpsc::channel,
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
thread,
|
thread,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
@ -140,36 +144,6 @@ fn arbiter_drop_no_panic_fut() {
|
||||||
arbiter.join().unwrap();
|
arbiter.join().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[allow(deprecated)]
|
|
||||||
fn arbiter_item_storage() {
|
|
||||||
let _ = System::new();
|
|
||||||
|
|
||||||
let arbiter = Arbiter::new();
|
|
||||||
|
|
||||||
assert!(!Arbiter::contains_item::<u32>());
|
|
||||||
Arbiter::set_item(42u32);
|
|
||||||
assert!(Arbiter::contains_item::<u32>());
|
|
||||||
|
|
||||||
Arbiter::get_item(|&item: &u32| assert_eq!(item, 42));
|
|
||||||
Arbiter::get_mut_item(|&mut item: &mut u32| assert_eq!(item, 42));
|
|
||||||
|
|
||||||
let thread = thread::spawn(move || {
|
|
||||||
Arbiter::get_item(|&_item: &u32| unreachable!("u32 not in this thread"));
|
|
||||||
})
|
|
||||||
.join();
|
|
||||||
assert!(thread.is_err());
|
|
||||||
|
|
||||||
let thread = thread::spawn(move || {
|
|
||||||
Arbiter::get_mut_item(|&mut _item: &mut i8| unreachable!("i8 not in this thread"));
|
|
||||||
})
|
|
||||||
.join();
|
|
||||||
assert!(thread.is_err());
|
|
||||||
|
|
||||||
arbiter.stop();
|
|
||||||
arbiter.join().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn no_system_current_panic() {
|
fn no_system_current_panic() {
|
||||||
|
@ -224,9 +198,71 @@ fn system_stop_stops_arbiters() {
|
||||||
System::current().stop();
|
System::current().stop();
|
||||||
sys.run().unwrap();
|
sys.run().unwrap();
|
||||||
|
|
||||||
|
// account for slightly slow thread de-spawns (only observed on windows)
|
||||||
|
thread::sleep(Duration::from_millis(100));
|
||||||
|
|
||||||
// arbiter should be dead and return false
|
// arbiter should be dead and return false
|
||||||
assert!(!Arbiter::current().spawn_fn(|| {}));
|
assert!(!Arbiter::current().spawn_fn(|| {}));
|
||||||
assert!(!arb.spawn_fn(|| {}));
|
assert!(!arb.spawn_fn(|| {}));
|
||||||
|
|
||||||
arb.join().unwrap();
|
arb.join().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_system_with_tokio() {
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
|
||||||
|
let res = System::with_tokio_rt(move || {
|
||||||
|
tokio::runtime::Builder::new_multi_thread()
|
||||||
|
.enable_io()
|
||||||
|
.enable_time()
|
||||||
|
.thread_keep_alive(Duration::from_millis(1000))
|
||||||
|
.worker_threads(2)
|
||||||
|
.max_blocking_threads(2)
|
||||||
|
.on_thread_start(|| {})
|
||||||
|
.on_thread_stop(|| {})
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.block_on(async {
|
||||||
|
actix_rt::time::sleep(Duration::from_millis(1)).await;
|
||||||
|
|
||||||
|
tokio::task::spawn(async move {
|
||||||
|
tx.send(42).unwrap();
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
123usize
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(res, 123);
|
||||||
|
assert_eq!(rx.recv().unwrap(), 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_arbiter_with_tokio() {
|
||||||
|
let _ = System::new();
|
||||||
|
|
||||||
|
let arb = Arbiter::with_tokio_rt(|| {
|
||||||
|
tokio::runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
let counter = Arc::new(AtomicBool::new(true));
|
||||||
|
|
||||||
|
let counter1 = counter.clone();
|
||||||
|
let did_spawn = arb.spawn(async move {
|
||||||
|
actix_rt::time::sleep(Duration::from_millis(1)).await;
|
||||||
|
counter1.store(false, Ordering::SeqCst);
|
||||||
|
Arbiter::current().stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
assert!(did_spawn);
|
||||||
|
|
||||||
|
arb.join().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(false, counter.load(Ordering::SeqCst));
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ description = "General purpose TCP server built for the Actix ecosystem"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
documentation = "https://docs.rs/actix-server/"
|
documentation = "https://docs.rs/actix-server"
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
exclude = [".gitignore", ".cargo/config"]
|
exclude = [".gitignore", ".cargo/config"]
|
||||||
|
@ -24,7 +24,7 @@ default = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-codec = "0.4.0-beta.1"
|
actix-codec = "0.4.0-beta.1"
|
||||||
actix-rt = { version = "2.0.0-beta.2", default-features = false }
|
actix-rt = { version = "2.0.0", default-features = false }
|
||||||
actix-service = "2.0.0-beta.3"
|
actix-service = "2.0.0-beta.3"
|
||||||
actix-utils = "3.0.0-beta.1"
|
actix-utils = "3.0.0-beta.1"
|
||||||
|
|
||||||
|
|
|
@ -24,5 +24,5 @@ futures-core = { version = "0.3.7", default-features = false }
|
||||||
pin-project-lite = "0.2"
|
pin-project-lite = "0.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "2.0.0-beta.2"
|
actix-rt = "2.0.0"
|
||||||
futures-util = { version = "0.3.7", default-features = false }
|
futures-util = { version = "0.3.7", default-features = false }
|
||||||
|
|
|
@ -2,6 +2,4 @@
|
||||||
|
|
||||||
> Service trait and combinators for representing asynchronous request/response operations.
|
> Service trait and combinators for representing asynchronous request/response operations.
|
||||||
|
|
||||||
See documentation for detailed explanations these components: [https://docs.rs/actix-service][docs].
|
See documentation for detailed explanations of these components: https://docs.rs/actix-service.
|
||||||
|
|
||||||
[docs]: https://docs.rs/actix-service
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ description = "TLS acceptor and connector services for Actix ecosystem"
|
||||||
keywords = ["network", "tls", "ssl", "async", "transport"]
|
keywords = ["network", "tls", "ssl", "async", "transport"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
documentation = "https://docs.rs/actix-tls/"
|
documentation = "https://docs.rs/actix-tls"
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
@ -41,7 +41,7 @@ uri = ["http"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-codec = "0.4.0-beta.1"
|
actix-codec = "0.4.0-beta.1"
|
||||||
actix-rt = { version = "2.0.0-beta.2", default-features = false }
|
actix-rt = { version = "2.0.0", default-features = false }
|
||||||
actix-service = "2.0.0-beta.3"
|
actix-service = "2.0.0-beta.3"
|
||||||
actix-utils = "3.0.0-beta.1"
|
actix-utils = "3.0.0-beta.1"
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ tls-native-tls = { package = "native-tls", version = "0.2", optional = true }
|
||||||
tokio-native-tls = { version = "0.3", optional = true }
|
tokio-native-tls = { version = "0.3", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "2.0.0-beta.2"
|
actix-rt = "2.0.0"
|
||||||
actix-server = "2.0.0-beta.2"
|
actix-server = "2.0.0-beta.2"
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
env_logger = "0.8"
|
env_logger = "0.8"
|
||||||
|
|
|
@ -6,7 +6,7 @@ description = "Support for tokio tracing with Actix services"
|
||||||
keywords = ["network", "framework", "tracing"]
|
keywords = ["network", "framework", "tracing"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
documentation = "https://docs.rs/actix-tracing/"
|
documentation = "https://docs.rs/actix-tracing"
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
@ -23,5 +23,5 @@ tracing = "0.1"
|
||||||
tracing-futures = "0.2"
|
tracing-futures = "0.2"
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev_dependencies]
|
||||||
actix-rt = "2.0.0-beta.2"
|
actix-rt = "2.0.0"
|
||||||
slab = "0.4"
|
slab = "0.4"
|
||||||
|
|
|
@ -6,7 +6,7 @@ description = "Various network related services and utilities for the Actix ecos
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
documentation = "https://docs.rs/actix-utils/"
|
documentation = "https://docs.rs/actix-utils"
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
@ -17,7 +17,7 @@ path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-codec = "0.4.0-beta.1"
|
actix-codec = "0.4.0-beta.1"
|
||||||
actix-rt = { version = "2.0.0-beta.2", default-features = false }
|
actix-rt = { version = "2.0.0", default-features = false }
|
||||||
actix-service = "2.0.0-beta.3"
|
actix-service = "2.0.0-beta.3"
|
||||||
|
|
||||||
futures-core = { version = "0.3.7", default-features = false }
|
futures-core = { version = "0.3.7", default-features = false }
|
||||||
|
|
|
@ -10,7 +10,7 @@ keywords = ["string", "bytes", "utf8", "web", "actix"]
|
||||||
categories = ["no-std", "web-programming"]
|
categories = ["no-std", "web-programming"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
documentation = "https://docs.rs/bytestring/"
|
documentation = "https://docs.rs/bytestring"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue