Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upStabilize std::thread #20615
Conversation
rust-highfive
assigned
pcwalton
Jan 6, 2015
This comment has been minimized.
This comment has been minimized.
|
r? @pcwalton (rust_highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
|
r? @alexcrichton |
rust-highfive
assigned
alexcrichton
and unassigned
pcwalton
Jan 6, 2015
This comment has been minimized.
This comment has been minimized.
|
This API makes sense, and it's good to see that this usecase will be supported in the standard library. The one concern I have is that with this API, you have no choice but to detach the thread immediately, which is a limitation that didn't previously exist. But I can't immediately think of a reason not to detach immediately if you were going to detach at all, so maybe this is acceptable. |
aturon
force-pushed the
aturon:stab-2-thread
branch
from
b026326
to
ca4380c
Jan 6, 2015
This comment has been minimized.
This comment has been minimized.
|
@pythonesque We could always re-introduce a Thanks for the feedback! |
This comment has been minimized.
This comment has been minimized.
|
I have the same concerns as @pythonesque. I like this API, but I think we should still have a way to explicitly Here's an example of a toy program that requires this ability: use std::thread::Thread;
use std::sync::mpsc::channel;
use std::rand::{self, Rng};
use std::io::timer::sleep;
use std::time::duration::Duration;
fn run_thread() {
let (tx, rx) = channel();
println!("running thread");
let guard = Thread::spawn(move || {
tx.send(rand::thread_rng().gen_range(0f32, 1f32)).unwrap();
println!("thread sleeping");
sleep(Duration::seconds(2));
println!("thread finished sleeping");
});
if rx.recv().unwrap() < 0.5 {
println!("detaching");
guard.detach()
} else {
println!("joining")
}
}
fn main() {
run_thread();
println!("exiting main thread");
} |
This comment has been minimized.
This comment has been minimized.
I'd suggest reintroducing |
This comment has been minimized.
This comment has been minimized.
|
Thanks for the feedback @kballard! Reintroducing as |
aturon
force-pushed the
aturon:stab-2-thread
branch
from
ca4380c
to
248b3c4
Jan 6, 2015
This comment has been minimized.
This comment has been minimized.
|
Added back |
This comment has been minimized.
This comment has been minimized.
|
Are we okay with panicing if thread creation fails? Should |
This comment has been minimized.
This comment has been minimized.
|
Ah yeah, that would be useful as well. |
alexcrichton
reviewed
Jan 6, 2015
| /// A handle to a thread. | ||
| pub struct Thread { | ||
| inner: Arc<Inner>, | ||
| } | ||
|
|
||
| #[stable] | ||
| unsafe impl Sync for Thread {} |
This comment has been minimized.
This comment has been minimized.
sfackler
reviewed
Jan 6, 2015
| @@ -525,17 +525,17 @@ mod tests { | |||
| #[test] | |||
| fn test_null_byte() { | |||
| use thread::Thread; | |||
| let result = Thread::spawn(move|| { | |||
| let result = Thread::scopedspawn(move|| { | |||
This comment has been minimized.
This comment has been minimized.
aturon
force-pushed the
aturon:stab-2-thread
branch
2 times, most recently
from
1c84946
to
6ee660b
Jan 6, 2015
This comment has been minimized.
This comment has been minimized.
It's a good question. My and @alexcrichton's instinct here is that this is a relatively niche concern that could be relegated to In any case, these are @alexcrichton Nits addressed. |
alexcrichton
reviewed
Jan 6, 2015
| @@ -0,0 +1,857 @@ | |||
| // Copyright 2012 The Rust Project Developers. See the COPYRIGHT | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@sfackler: It's not much different from memory allocation failing. It needs to be handled in robust software but Rust's libraries are not usable for that anyway. |
alexcrichton
reviewed
Jan 6, 2015
| pub struct JoinGuard<T> { | ||
| #[must_use] | ||
| #[unstable = "may change with specifics of new Send semantics"] | ||
| pub struct JoinGuard<'a, T> { |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
This is a pretty conservative step, so r=me with a few nits, we've still got some room to tweak interfaces here and there as necessary. |
aturon
force-pushed the
aturon:stab-2-thread
branch
from
6ee660b
to
1bd26f7
Jan 6, 2015
This comment has been minimized.
This comment has been minimized.
|
@thestinger Failing to initialize a new thread happens a lot more often than failing to allocate memory (at least in my experience). Though I guess in some sense the problem fixes itself by killing the thread :P |
This comment has been minimized.
This comment has been minimized.
|
And conversely, thread creation is comparatively much rarer than memory allocation so the cost of returning a |
This comment has been minimized.
This comment has been minimized.
|
On the implementation side, would it be better to use Option instead of having a "joined" flag? That should save a word in the struct size. |
aturon
force-pushed the
aturon:stab-2-thread
branch
from
1bd26f7
to
7bf6892
Jan 6, 2015
This comment has been minimized.
This comment has been minimized.
|
@pythonesque @sfackler @alexcrichton I talked with some of you all about this on IRC, but: I think a good middle ground here is for the Usually we avoid such duplication (i.e., no All that said, I'd like to move forward with this PR as-is since there's a limited window to land these changes before alpha. Since the relevant bits of the API are |
This comment has been minimized.
This comment has been minimized.
|
Seems reasonable to me. |
This comment has been minimized.
This comment has been minimized.
|
|
aturon
force-pushed the
aturon:stab-2-thread
branch
from
7bf6892
to
caca9b2
Jan 6, 2015
This comment has been minimized.
This comment has been minimized.
alexcrichton
commented on caca9b2
Jan 6, 2015
|
r+ |
aturon commentedJan 6, 2015
This commit takes a first pass at stabilizing
std::thread:It removes the
detachmethod in favor of two constructors --spawnfor detached threads,
scopedfor "scoped" (i.e., must-join)threads. This addresses some of the surprise/frustrating debug
sessions with the previous API, in which
spawnproduced a guard thaton destruction joined the thread (unless
detachwas called).The reason to have the division in part is that
Sendwill soon notimply
'static, which means thatscopedthread creation can take aclosure over shared stack data of the parent thread. On the other
hand, this means that the parent must not pop the relevant stack
frames while the child thread is running. The
JoinGuardis used toprevent this from happening by joining on drop (if you have not
already explicitly
joined.) The APIs aroundscopedarefuture-proofed for the
Sendchanges by taking an additional lifetimeparameter. With the current definition of
Send, this is forced to be'static, but whenSendchanges these APIs will gain their fullflexibility immediately.
Threads that are
spawned, on the other hand, are detached from thestart and do not yield an RAII guard.
The hope is that, by making
scopedan explicit opt-in with a verysuggestive name, it will be drastically less likely to be caught by a
surprising deadlock due to an implicit join at the end of a scope.
The module itself is marked stable.
Existing methods other than
spawnandscopedare marked stable.The migration path is:
becomes
while
becomes
[breaking-change]