Skip to content

Commit ee7a85c

Browse files
committed
Only box the function once when creating threads.
1 parent 0c4d81f commit ee7a85c

File tree

4 files changed

+55
-24
lines changed

4 files changed

+55
-24
lines changed

src/libstd/sys/common/thread.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,13 @@
1111
use prelude::v1::*;
1212

1313
use alloc::boxed::FnBox;
14-
use libc;
1514
use sys::stack_overflow;
1615

17-
pub unsafe fn start_thread(main: *mut libc::c_void) {
16+
pub unsafe fn start_thread<'a>(main: Box<FnBox() + 'a>) {
1817
// Next, set up our stack overflow handler which may get triggered if we run
1918
// out of stack.
2019
let _handler = stack_overflow::Handler::new();
2120

2221
// Finally, let's run some code.
23-
Box::from_raw(main as *mut Box<FnBox()>)()
22+
main();
2423
}

src/libstd/sys/unix/thread.rs

+28-11
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
use prelude::v1::*;
1212

13-
use alloc::boxed::FnBox;
1413
use cmp;
1514
#[cfg(not(any(target_env = "newlib", target_os = "solaris")))]
1615
use ffi::CString;
@@ -33,9 +32,33 @@ unsafe impl Send for Thread {}
3332
unsafe impl Sync for Thread {}
3433

3534
impl Thread {
36-
pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
35+
pub unsafe fn new<F: FnOnce()>(stack: usize, p: F)
3736
-> io::Result<Thread> {
37+
38+
extern fn thread_start<F: FnOnce()>(main: *mut libc::c_void)
39+
-> *mut libc::c_void {
40+
unsafe {
41+
let main = Box::from_raw(main as *mut F);
42+
start_thread(main);
43+
}
44+
ptr::null_mut()
45+
}
46+
3847
let p = box p;
48+
49+
match Thread::new_inner(stack, &*p as *const _ as *const _, thread_start::<F>) {
50+
Ok(thread) => {
51+
mem::forget(p); // ownership passed to pthread_create
52+
Ok(thread)
53+
}
54+
55+
Err(e) => Err(e),
56+
}
57+
}
58+
59+
unsafe fn new_inner(stack: usize, p: *const libc::c_void,
60+
f: extern fn(*mut libc::c_void) -> *mut libc::c_void)
61+
-> io::Result<Thread> {
3962
let mut native: libc::pthread_t = mem::zeroed();
4063
let mut attr: libc::pthread_attr_t = mem::zeroed();
4164
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
@@ -59,20 +82,14 @@ impl Thread {
5982
}
6083
};
6184

62-
let ret = libc::pthread_create(&mut native, &attr, thread_start,
63-
&*p as *const _ as *mut _);
85+
let ret = libc::pthread_create(&mut native, &attr, f,
86+
p as *mut _);
6487
assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
6588

66-
return if ret != 0 {
89+
if ret != 0 {
6790
Err(io::Error::from_raw_os_error(ret))
6891
} else {
69-
mem::forget(p); // ownership passed to pthread_create
7092
Ok(Thread { id: native })
71-
};
72-
73-
extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
74-
unsafe { start_thread(main); }
75-
ptr::null_mut()
7693
}
7794
}
7895

src/libstd/sys/windows/thread.rs

+24-9
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,31 @@ pub struct Thread {
2525
}
2626

2727
impl Thread {
28-
pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
28+
pub unsafe fn new<F: FnOnce()>(stack: usize, p: F)
2929
-> io::Result<Thread> {
30+
extern "system" fn thread_start<F: FnOnce()>(main: *mut c_void)
31+
-> c::DWORD {
32+
unsafe {
33+
let main = Box::from_raw(main as *mut F);
34+
start_thread(main);
35+
}
36+
0
37+
}
38+
3039
let p = box p;
3140

41+
match Thread::new_inner(stack, &*p as *const _ as *const _, thread_start::<F>) {
42+
Ok(thread) => {
43+
mem::forget(p); // ownership passed to CreateThread
44+
Ok(thread)
45+
}
46+
Err(e) => Err(e),
47+
}
48+
}
49+
50+
unsafe fn new_inner(stack: usize, p: *const c_void,
51+
f: extern "system" fn(*mut c_void) -> c::DWORD)
52+
-> io::Result<Thread> {
3253
// FIXME On UNIX, we guard against stack sizes that are too small but
3354
// that's because pthreads enforces that stacks are at least
3455
// PTHREAD_STACK_MIN bytes big. Windows has no such lower limit, it's
@@ -37,21 +58,15 @@ impl Thread {
3758
// Round up to the next 64 kB because that's what the NT kernel does,
3859
// might as well make it explicit.
3960
let stack_size = (stack + 0xfffe) & (!0xfffe);
40-
let ret = c::CreateThread(ptr::null_mut(), stack_size,
41-
thread_start, &*p as *const _ as *mut _,
61+
let ret = c::CreateThread(ptr::null_mut(), stack,
62+
f, p as *mut _,
4263
0, ptr::null_mut());
4364

4465
return if ret as usize == 0 {
4566
Err(io::Error::last_os_error())
4667
} else {
47-
mem::forget(p); // ownership passed to CreateThread
4868
Ok(Thread { handle: Handle::new(ret) })
4969
};
50-
51-
extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
52-
unsafe { start_thread(main); }
53-
0
54-
}
5570
}
5671

5772
pub fn set_name(_name: &str) {

src/libstd/thread/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ impl Builder {
284284

285285
Ok(JoinHandle(JoinInner {
286286
native: unsafe {
287-
Some(try!(imp::Thread::new(stack_size, Box::new(main))))
287+
Some(try!(imp::Thread::new(stack_size, main)))
288288
},
289289
thread: my_thread,
290290
packet: Packet(my_packet),

0 commit comments

Comments
 (0)