Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement a new task spawning model not depending on a managed runtime #18000

Closed
thestinger opened this issue Oct 13, 2014 · 5 comments · Fixed by #19654
Closed

implement a new task spawning model not depending on a managed runtime #18000

thestinger opened this issue Oct 13, 2014 · 5 comments · Fixed by #19654
Labels
A-FFI Area: Foreign function interface (FFI) C-enhancement Category: An issue proposing an enhancement or a PR with one. I-slow Issue: Problems and improvements with respect to performance of generated code.

Comments

@thestinger
Copy link
Contributor

Blocking threads on their children adds significant overhead and implies that Rust needs to be hosted in a runtime that's not compatible with the C model. Rust should be able to run on threads started from C without giving up the concurrency libraries. Higher-level abstractions can be built upon the primitives provided by the standard library, but it's not the place of the standard library to force subjective high-level design decisions with overhead onto applications.

The native model has both detached threads without the overhead of synchronization between the parent and child (as there is no hierarchy) and threads represented by objects that are joined in the destructor to avoid the need for additional synchronization primitives like channels in common cases. Rust needs to move to a model like this in order to complete the runtime removal RFC.

The API also uses proc, which is probably going to change before 1.0 because it will be replaced as as a distinct type by Box<FnOnce<...>>. It might stay around as a form of sugar but marking any API using the old closures as stable is premature.

@thestinger thestinger added A-libs I-slow Issue: Problems and improvements with respect to performance of generated code. C-enhancement Category: An issue proposing an enhancement or a PR with one. A-FFI Area: Foreign function interface (FFI) labels Oct 13, 2014
@pnkfelix
Copy link
Member

Assigning P-backcompat-libs, not 1.0 milestone.

(Also, there will be a forthcoming RFC regarding the relationship of stability markers and semver, which may illuminate some of the meta issues here...)

@thestinger thestinger changed the title task::spawn shouldn't be stable, concurrency should work without a managed runtime implement a new task spawning model not depending on a managed runtime Nov 10, 2014
@seanmonstar
Copy link
Contributor

Any reason tasks require a boxed closure? Is it just to prevent codegen bloat of having such a common function use generics?

I'd be interested in spawning a task without the extra box.

@thestinger
Copy link
Contributor Author

The overhead is insignificant due to the cost of making the stack allocation. It needs a to pass a function pointer and data parameter to a C function, and it needs to be bounded by Send. The Box<FnOnce<...>> type is the natural fit.

@aturon
Copy link
Member

aturon commented Nov 15, 2014

See #18967 for some discussion on the thread semantics. This change is likely RFC-worthy.

@aturon
Copy link
Member

aturon commented Nov 15, 2014

(I'm likely to prepare an RFC amendment to RFC 230, or perhaps a separate RFC on the threading API.)

aturon added a commit to aturon/rust that referenced this issue Dec 19, 2014
Also removes:

* `std::task`
* `std::rt::task`
* `std::rt::thread`

Notes for the new API are in a follow-up commit.

Closes rust-lang#18000
aturon added a commit to aturon/rust that referenced this issue Dec 19, 2014
This commit is part of a series that introduces a `std::thread` API to
replace `std::task`.

In the new API, `spawn` returns a `JoinGuard`, which by default will
join the spawned thread when dropped. It can also be used to join
explicitly at any time, returning the thread's result. Alternatively,
the spawned thread can be explicitly detached (so no join takes place).

As part of this change, Rust processes now terminate when the main
thread exits, even if other detached threads are still running, moving
Rust closer to standard threading models. This new behavior may break code
that was relying on the previously implicit join-all.

In addition to the above, the new thread API also offers some built-in
support for building blocking abstractions in user space; see the module
doc for details.

Closes rust-lang#18000

[breaking-change]
bors added a commit that referenced this issue Dec 19, 2014
This PR substantially narrows the notion of a "runtime" in Rust, and allows calling into Rust code directly without any setup or teardown. 

After this PR, the basic "runtime support" in Rust will consist of:

* Unwinding and backtrace support
* Stack guards

Other support, such as helper threads for timers or the notion of a "current thread" are initialized automatically upon first use.

When using Rust in an embedded context, it should now be possible to call a Rust function directly as a C function with absolutely no setup, though in that case panics will cause the process to abort. In this regard, the C/Rust interface will look much like the C/C++ interface.

In more detail, this PR:

* Merges `librustrt` back into `std::rt`, undoing the facade. While doing so, it removes a substantial amount of redundant functionality (such as mutexes defined in the `rt` module). Code using `librustrt` can now call into `std::rt` to e.g. start executing Rust code with unwinding support.

* Allows all runtime data to be initialized lazily, including the "current thread", the "at_exit" infrastructure, and the "args" storage.

* Deprecates and largely removes `std::task` along with the widespread requirement that there be a "current task" for many APIs in `std`. The entire task infrastructure is replaced with `std::thread`, which provides a more standard API for manipulating and creating native OS threads. In particular, it's possible to join on a created thread, and to get a handle to the currently-running thread. In addition, threads are equipped with some basic blocking support in the form of `park`/`unpark` operations (following a tradition in some OSes as well as the JVM). See the `std::thread` documentation for more details.

* Channels are refactored to use a new internal blocking infrastructure that itself sits on top of `park`/`unpark`.

One important change here is that a Rust program ends when its main thread does, following most threading models. On the other hand, threads will often be created with an RAII-style join handle that will re-institute blocking semantics naturally (and with finer control).

This is very much a:

[breaking-change]

Closes #18000
r? @alexcrichton
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-FFI Area: Foreign function interface (FFI) C-enhancement Category: An issue proposing an enhancement or a PR with one. I-slow Issue: Problems and improvements with respect to performance of generated code.
Projects
None yet
4 participants