bcb05a0ab2
Unchecked thread spawning # Summary Add an unsafe interface for spawning lifetime-unrestricted threads for library authors to build less-contrived, less-hacky safe abstractions on. # Motivation So a few years back scoped threads were entirely removed from the Rust stdlib, the reason being that it was possible to leak the scoped thread's join guards without resorting to unsafe code, which meant the concept was not completely safe, either. Only a maximally-restrictive safe API for thread spawning was kept in the stdlib, that requires `'static` lifetime bounds on both the thread closure and its return type. A number of 3rd party libraries sprung up to offer their implementations for safe scoped threads implementations. These work by essentially hiding the join guards from the user, thus forcing them to join at the end of an (internal) function scope. However, since these libraries have to use the maximally restrictive thread spawning API, they have to resort to some very contrived manipulations and subversions of Rust's type system to basically achieve what this commit does with some minimal restructuring of the current code and exposing a new unsafe function signature for spawning threads without lifetime restrictions. Obviously this is unsafe, but its main use would be to allow library authors to write safe abstractions with and around it. To further illustrate my point, here's a quick summary of the hoops that, for instance `crossbeam`, has to jump through to spawn a lifetime unrestricted thread, all of which would not be necessary if an unsafe API existed as part of the stdlib: 1. Allocate an `Arc<Option<T>>` on the heap where the result with type `T: 'a` will go (in practice requires `Mutex` or `UnsafeCell` as well). 2. Wrap the desired thread closure with lifetime bound `'a` into another closure (also `..: 'a`) that returns `()`, executes the inner closure and writes its result into the pre-allocated `Option<T>`. 3. Box the wrapping closure, cast it to a trait object (`FnBox`) and (unsafely) transmute its lifetime bound from `'a` to `'static`. So while this new `spawn_unchecked` function is certainly not very relevant for general use, since scoped threads are so common I think it makes sense to expose an interface for libraries implementing these to build on. The changes implemented are also very minimal: The current `spawn` function (which internally contains unsafe code) is moved into an unsafe `spawn_unchecked` function, which the safe function then wraps around. # Issues - ~~so far, no documentation for the new function (yet)~~ - the name of the function might be controversial, as `*_unchecked` more commonly indicates that some sort of runtime check is omitted (`unrestricted` may be more fitting) - if accepted, it might make sense to add a freestanding `thread::spawn_unchecked` function similar to the current `thread::spawn` for convenience. |
||
---|---|---|
.. | ||
collections | ||
ffi | ||
io | ||
net | ||
os | ||
prelude | ||
sync | ||
sys | ||
sys_common | ||
tests | ||
thread | ||
alloc.rs | ||
ascii.rs | ||
build.rs | ||
Cargo.toml | ||
env.rs | ||
error.rs | ||
f32.rs | ||
f64.rs | ||
fs.rs | ||
future.rs | ||
keyword_docs.rs | ||
lib.rs | ||
macros.rs | ||
memchr.rs | ||
num.rs | ||
panic.rs | ||
panicking.rs | ||
path.rs | ||
primitive_docs.rs | ||
process.rs | ||
rt.rs | ||
time.rs |