Skip to content

Commit

Permalink
WIP: task::scope using implicit scopes
Browse files Browse the repository at this point in the history
This change adds task::scope as a mechanism for supporting
structured concurrency as described in tokio-rs#1879.

This version of the scope implementation makes use of implicit scopes,
which are propgated within the task system through task local storage.

Ever task spawned via `scope::spawn` or `scope::spawn_cancellable` is
automatically attached to it's current scope without having to
explicitly attach to it. This provides stronger guarantees, since child
tasks in this model will never be able to outlive the parent - there is
no `ScopeHandle` available to spawn a task on a certain scope after this
is finished.

One drawback of this approach is however that since no `ScopeHandle` is
available, we also can't tie the lifetime of tasks and their
`JoinHandle`s to this scope. This makes it less likely that we could
borrowing data from the parent task using this approach.

One benefit however is that there seems to be an interesting migration
path from tokios current task system to this scoped approach:
- Using `tokio::spawn` could in the future be equivalent to spawning
  a task on the runtimes implicit top level scope. The task would not
  be force-cancellable, in the same fashion as tasks spawned via
  `scope::spawn` are not cancellable.
- Shutting down the runtime could be equivalent to leaving a scope: The
  remaining running tasks get a graceful cancellation signal and the
  scope would wait for those tasks to finish.
- However since the Runtime would never have to force-cancel a task
  (people would opt into this behavior using `scope::spawn_cancellable`)
  the `JoinError` could be removed from the "normal" spawn API. It is
  still available for cancellable spawns.
  • Loading branch information
Matthias247 committed Jun 2, 2020
1 parent db0d6d7 commit 699d19e
Show file tree
Hide file tree
Showing 7 changed files with 1,091 additions and 1 deletion.
6 changes: 5 additions & 1 deletion tokio/Cargo.toml
Expand Up @@ -41,10 +41,12 @@ full = [
"rt-core",
"rt-util",
"rt-threaded",
"scope",
"signal",
"stream",
"sync",
"time",
"futures"
]

blocking = ["rt-core"]
Expand Down Expand Up @@ -73,6 +75,7 @@ rt-threaded = [
"num_cpus",
"rt-core",
]
scope = []
signal = [
"io-driver",
"lazy_static",
Expand All @@ -99,6 +102,7 @@ pin-project-lite = "0.1.1"
# Everything else is optional...
fnv = { version = "1.0.6", optional = true }
futures-core = { version = "0.3.0", optional = true }
futures = { version = "0.3.0", optional = true }
lazy_static = { version = "1.0.2", optional = true }
memchr = { version = "2.2", optional = true }
mio = { version = "0.6.20", optional = true }
Expand All @@ -122,7 +126,7 @@ optional = true

[dev-dependencies]
tokio-test = { version = "0.2.0", path = "../tokio-test" }
futures = { version = "0.3.0", features = ["async-await"] }
futures = { version = "0.3.0", features = ["async-await", "executor"] }
futures-test = "0.3.0"
proptest = "0.9.4"
tempfile = "3.1.0"
Expand Down
10 changes: 10 additions & 0 deletions tokio/src/macros/cfg.rs
Expand Up @@ -204,6 +204,16 @@ macro_rules! cfg_process {
}
}

macro_rules! cfg_scope {
($($item:item)*) => {
$(
#[cfg(feature = "scope")]
#[cfg_attr(docsrs, doc(cfg(feature = "scope")))]
$item
)*
}
}

macro_rules! cfg_signal {
($($item:item)*) => {
$(
Expand Down
5 changes: 5 additions & 0 deletions tokio/src/sync/mod.rs
Expand Up @@ -460,6 +460,11 @@ cfg_sync! {
mod task;
pub(crate) use task::AtomicWaker;

cfg_unstable! {
mod wait_group;
pub(crate) use wait_group::{SharedWaitGroup};
}

pub mod watch;
}

Expand Down

0 comments on commit 699d19e

Please sign in to comment.