use std::os;
use std::str;
use std::string::String;
-use std::task;
+use std::thread::Thread;
use std::time::Duration;
use test::MetricMap;
loop {
//waiting 1 second for gdbserver start
timer::sleep(Duration::milliseconds(1000));
- let result = task::try(move || {
+ let result = Thread::with_join(move || {
tcp::TcpStream::connect("127.0.0.1:5039").unwrap();
- });
+ }).join();
if result.is_err() {
continue;
}
(representing termination with an error).
```{rust}
-# use std::task;
+# use std::thread::Thread;
# fn some_condition() -> bool { false }
# fn calculate_result() -> int { 0 }
-let result: Result<int, Box<std::any::Any + Send>> = task::try(move || {
+let result: Result<int, Box<std::any::Any + Send>> = Thread::with_join(move || {
if some_condition() {
calculate_result()
} else {
panic!("oops!");
}
-});
+}).join();
assert!(result.is_err());
```
/// Trait for moving into a `Cow`
pub trait IntoCow<'a, T, Sized? B> {
- /// Moves `self` into `Cow`
+ /// Moves `serlf` into `Cow`
fn into_cow(self) -> Cow<'a, T, B>;
}
use std::any::AnyRefExt;
use std::io;
use std::os;
-use std::task::TaskBuilder;
+use std::thread;
use rustc::session::early_error;
static STACK_SIZE: uint = 32000000; // 32MB
let (tx, rx) = channel();
- let w = io::ChanWriter::new(tx);
+ let mut w = Some(io::ChanWriter::new(tx)); // option dance
let mut r = io::ChanReader::new(rx);
- let mut task = TaskBuilder::new().named("rustc").stderr(box w);
+ let mut cfg = thread::cfg().name("rustc".to_string());
// FIXME: Hacks on hacks. If the env is trying to override the stack size
// then *don't* set it explicitly.
if os::getenv("RUST_MIN_STACK").is_none() {
- task = task.stack_size(STACK_SIZE);
+ cfg = cfg.stack_size(STACK_SIZE);
}
- match task.try(f) {
+ let f = proc() {
+ std::io::stdio::set_stderr(box w.take().unwrap());
+ f()
+ };
+ match cfg.with_join(f).join() {
Ok(()) => { /* fallthrough */ }
Err(value) => {
// Task panicked without emitting a fatal diagnostic
let result = run(args);
std::os::set_exit_status(result);
}
-
use std::str;
use std::mem;
use std::sync::{Arc, Mutex};
-use std::task::TaskBuilder;
+use std::thread;
use libc::{c_uint, c_int, c_void};
#[deriving(Clone, PartialEq, PartialOrd, Ord, Eq)]
let diag_emitter = diag_emitter.clone();
let remark = sess.opts.cg.remark.clone();
- let future = TaskBuilder::new().named(format!("codegen-{}", i)).try_future(move |:| {
+ let (tx, rx) = channel();
+ let mut tx = Some(tx);
+ futures.push(rx);
+
+ thread::cfg().name(format!("codegen-{}", i)).spawn(move |:| {
let diag_handler = mk_handler(box diag_emitter);
// Must construct cgcx inside the proc because it has non-Send
None => break,
}
}
+
+ tx.take().unwrap().send(());
});
- futures.push(future);
}
let mut panicked = false;
- for future in futures.into_iter() {
- match future.into_inner() {
+ for rx in futures.into_iter() {
+ match rx.recv_opt() {
Ok(()) => {},
Err(_) => {
panicked = true;
let cr = Path::new(cratefile);
info!("starting to run rustc");
- let (mut krate, analysis) = std::task::try(move |:| {
+
+ let (mut krate, analysis) = std::thread::Thread::with_join(move |:| {
let cr = cr;
core::run_core(libs, cfgs, externs, &cr, triple)
- }).map_err(|_| "rustc failed").unwrap();
+ }).join().map_err(|_| "rustc failed").unwrap();
info!("finished with rustc");
let mut analysis = Some(analysis);
ANALYSISKEY.with(|s| {
use std::str;
use std::string::String;
use std::thunk::Thunk;
+use std::thread::Thread;
use std::collections::{HashSet, HashMap};
use testing;
let w1 = io::ChanWriter::new(tx);
let w2 = w1.clone();
let old = io::stdio::set_stderr(box w1);
- spawn(move |:| {
+ Thread::spawn(move |:| {
let mut p = io::ChanReader::new(rx);
let mut err = match old {
Some(old) => {
mod tests {
use prelude::*;
use ptr;
- use task;
+ use thread::Thread;
use libc;
use super::*;
#[test]
fn test_to_c_str_fail() {
- assert!(task::try(move|| { "he\x00llo".to_c_str() }).is_err());
+ assert!(Thread::with_join(move|| { "he\x00llo".to_c_str() }).join().is_err());
}
#[test]
no_send: NoSend,
}
-fn token() -> (WaitToken, SignalToken) {
+pub fn tokens() -> (WaitToken, SignalToken) {
let inner = Arc::new(Inner {
thread: Thread::current(),
woken: INIT_ATOMIC_BOOL,
}
impl SignalToken {
- fn signal(&self) -> bool {
+ pub fn signal(&self) -> bool {
let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
if wake {
self.inner.thread.unpark();
}
impl WaitToken {
- fn wait(self) {
+ pub fn wait(self) {
while !self.inner.woken.load(Ordering::SeqCst) {
Thread::park()
}
use core::mem;
use core::cell::UnsafeCell;
-pub use comm::select::{Select, Handle};
-use comm::select::StartResult::*;
+pub use self::select::{Select, Handle};
+use self::select::StartResult;
+use self::select::StartResult::*;
+use self::blocking::SignalToken;
macro_rules! test {
{ fn $name:ident() $b:block $(#[$a:meta])*} => (
use comm::*;
use super::*;
- use task;
+ use thread::Thread;
$(#[$a])* #[test] fn f() { $b }
}
(a, ret)
}
oneshot::UpDisconnected => (a, Err(t)),
- oneshot::UpWoke(task) => {
- // This send cannot panic because the task is
+ oneshot::UpWoke(token) => {
+ // This send cannot panic because the thread is
// asleep (we're looking at it), so the receiver
// can't go away.
(*a.get()).send(t).ok().unwrap();
- task.wake().map(|t| t.reawaken());
+ token.signal();
(a, Ok(()))
}
}
}
}
- fn start_selection(&self, mut token: SignalToken) -> bool {
+ fn start_selection(&self, mut token: SignalToken) -> StartResult {
loop {
let (t, new_port) = match *unsafe { self.inner() } {
Oneshot(ref p) => {
test! { fn oneshot_single_thread_recv_chan_close() {
// Receiving on a closed chan will panic
- let res = task::try(move|| {
+ let res = Thread::with_join(move|| {
let (tx, rx) = channel::<int>();
drop(tx);
rx.recv();
- });
+ }).join();
// What is our res?
assert!(res.is_err());
} }
spawn(move|| {
drop(tx);
});
- let res = task::try(move|| {
+ let res = Thread::with_join(move|| {
assert!(rx.recv() == box 10);
- });
+ }).join();
assert!(res.is_err());
} }
spawn(move|| {
drop(rx);
});
- let _ = task::try(move|| {
+ let _ = Thread::with_join(move|| {
tx.send(1);
- });
+ }).join();
}
} }
test! { fn oneshot_multi_thread_recv_close_stress() {
for _ in range(0, stress_factor()) {
let (tx, rx) = channel::<int>();
- spawn(move|| {
- let res = task::try(move|| {
+ spawn(proc() {
+ let res = Thread::with_join(move|| {
rx.recv();
- });
+ }).join();
assert!(res.is_err());
});
spawn(move|| {
tx2.send(());
});
// make sure the other task has gone to sleep
- for _ in range(0u, 5000) { task::deschedule(); }
+ for _ in range(0u, 5000) { Thread::yield_now(); }
// upgrade to a shared chan and send a message
let t = tx.clone();
// wait for the child task to exit before we exit
rx2.recv();
- } }
-
- test! { fn sends_off_the_runtime() {
- use rt::thread::Thread;
-
- let (tx, rx) = channel();
- let t = Thread::start(move|| {
- for _ in range(0u, 1000) {
- tx.send(());
- }
- });
- for _ in range(0u, 1000) {
- rx.recv();
- }
- t.join();
- } }
-
- test! { fn try_recvs_off_the_runtime() {
- use rt::thread::Thread;
-
- let (tx, rx) = channel();
- let (cdone, pdone) = channel();
- let t = Thread::start(move|| {
- let mut hits = 0u;
- while hits < 10 {
- match rx.try_recv() {
- Ok(()) => { hits += 1; }
- Err(Empty) => { Thread::yield_now(); }
- Err(Disconnected) => return,
- }
- }
- cdone.send(());
- });
- for _ in range(0u, 10) {
- tx.send(());
- }
- t.join();
- pdone.recv();
- } }
+ })
}
#[cfg(test)]
test! { fn oneshot_single_thread_recv_chan_close() {
// Receiving on a closed chan will panic
- let res = task::try(move|| {
+ let res = Thread::with_join(move|| {
let (tx, rx) = sync_channel::<int>(0);
drop(tx);
rx.recv();
- });
+ }).join();
// What is our res?
assert!(res.is_err());
} }
spawn(move|| {
drop(tx);
});
- let res = task::try(move|| {
+ let res = Thread::with_join(move|| {
assert!(rx.recv() == box 10);
- });
+ }).join();
assert!(res.is_err());
} }
spawn(move|| {
drop(rx);
});
- let _ = task::try(move|| {
+ let _ = Thread::with_join(move || {
tx.send(1);
- });
+ }).join();
}
} }
test! { fn oneshot_multi_thread_recv_close_stress() {
for _ in range(0, stress_factor()) {
let (tx, rx) = sync_channel::<int>(0);
- spawn(move|| {
- let res = task::try(move|| {
+ spawn(proc() {
+ let res = Thread::with_join(move|| {
rx.recv();
- });
+ }).join();
assert!(res.is_err());
});
spawn(move|| {
tx2.send(());
});
// make sure the other task has gone to sleep
- for _ in range(0u, 5000) { task::deschedule(); }
+ for _ in range(0u, 5000) { Thread::yield_now(); }
// upgrade to a shared chan and send a message
let t = tx.clone();
rx2.recv();
} }
- test! { fn try_recvs_off_the_runtime() {
- use rt::thread::Thread;
-
- let (tx, rx) = sync_channel::<()>(0);
- let (cdone, pdone) = channel();
- let t = Thread::start(move|| {
- let mut hits = 0u;
- while hits < 10 {
- match rx.try_recv() {
- Ok(()) => { hits += 1; }
- Err(Empty) => { Thread::yield_now(); }
- Err(Disconnected) => return,
- }
- }
- cdone.send(());
- });
- for _ in range(0u, 10) {
- tx.send(());
- }
- t.join();
- pdone.recv();
- } }
-
test! { fn send_opt1() {
let (tx, rx) = sync_channel::<int>(0);
spawn(move|| { rx.recv(); });
test! { fn try_send4() {
let (tx, rx) = sync_channel::<int>(0);
spawn(move|| {
- for _ in range(0u, 1000) { task::deschedule(); }
+ for _ in range(0u, 1000) { Thread::yield_now(); }
assert_eq!(tx.try_send(1), Ok(()));
});
assert_eq!(rx.recv(), 1);
use core::prelude::*;
-use alloc::boxed::Box;
use comm::Receiver;
-use comm::blocking::{mod, WaitToken, SignalToken};
+use comm::blocking::{mod, SignalToken};
use core::mem;
use sync::atomic;
// Attempt to not block the task (it's a little expensive). If it looks
// like we're not empty, then immediately go through to `try_recv`.
if self.state.load(atomic::SeqCst) == EMPTY {
- let (wait_token, signal_token) = blocking::token();
+ let (wait_token, signal_token) = blocking::tokens();
let ptr = unsafe { signal_token.cast_to_uint() };
// race with senders to enter the blocking state
// If we've got a blocked task, then use an atomic to gain ownership
// of it (may fail)
- BLOCKED => self.state.compare_and_swap(BLOCKED, EMPTY, atomic::SeqCst)
+ ptr => self.state.compare_and_swap(ptr, EMPTY, atomic::SeqCst)
};
// Now that we've got ownership of our state, figure out what to do
use core::prelude::*;
-use alloc::boxed::Box;
use core::cell::Cell;
use core::kinds::marker;
use core::mem;
use comm::Receiver;
use comm::blocking::{mod, SignalToken};
-use self::StartResult::*;
-
/// The "receiver set" of the select interface. This structure is used to manage
/// a set of receivers which are being selected over.
pub struct Select {
let (wait_token, signal_token) = blocking::tokens();
for (i, handle) in self.iter().enumerate() {
match (*handle).packet.start_selection(signal_token.clone()) {
- Installed => {}
- Abort => {
+ StartResult::Installed => {}
+ StartResult::Abort => {
// Go back and abort the already-begun selections
for handle in self.iter().take(i) {
(*handle).packet.abort_selection();
let (tx3, rx3) = channel::<int>();
spawn(move|| {
- for _ in range(0u, 20) { task::deschedule(); }
+ for _ in range(0u, 20) { Thread::yield_now(); }
tx1.send(1);
rx3.recv();
- for _ in range(0u, 20) { task::deschedule(); }
+ for _ in range(0u, 20) { Thread::yield_now(); }
});
select! {
let (tx3, rx3) = channel::<()>();
spawn(move|| {
- for _ in range(0u, 20) { task::deschedule(); }
+ for _ in range(0u, 20) { Thread::yield_now(); }
tx1.send(1);
tx2.send(2);
rx3.recv();
tx3.send(());
});
- for _ in range(0u, 1000) { task::deschedule(); }
+ for _ in range(0u, 1000) { Thread::yield_now(); }
drop(tx1.clone());
tx2.send(());
rx3.recv();
tx2.send(());
});
- for _ in range(0u, 100) { task::deschedule() }
+ for _ in range(0u, 100) { Thread::yield_now() }
tx1.send(());
rx2.recv();
} }
tx2.send(());
});
- for _ in range(0u, 100) { task::deschedule() }
+ for _ in range(0u, 100) { Thread::yield_now() }
tx1.send(());
rx2.recv();
} }
tx2.send(());
});
- for _ in range(0u, 100) { task::deschedule() }
+ for _ in range(0u, 100) { Thread::yield_now() }
tx1.send(());
rx2.recv();
} }
test! { fn sync2() {
let (tx, rx) = sync_channel::<int>(0);
spawn(move|| {
- for _ in range(0u, 100) { task::deschedule() }
+ for _ in range(0u, 100) { Thread::yield_now() }
tx.send(1);
});
select! {
use core::prelude::*;
-use alloc::boxed::Box;
use core::cmp;
use core::int;
use comm::blocking::{mod, SignalToken};
use comm::select::StartResult;
use comm::select::StartResult::*;
+use thread::Thread;
const DISCONNECTED: int = int::MIN;
const FUDGE: int = 1024;
use core::prelude::*;
-use alloc::boxed::Box;
use core::cmp;
use core::int;
use thread::Thread;
use sync::atomic;
use comm::spsc_queue as spsc;
use comm::Receiver;
-use comm::blocking::{mod, WaitToken, SignalToken};
+use comm::blocking::{mod, SignalToken};
const DISCONNECTED: int = int::MIN;
#[cfg(test)]
let ptr = self.to_wake.load(atomic::SeqCst);
self.to_wake.store(0, atomic::SeqCst);
assert!(ptr != 0);
- unsafe { SignaToken::cast_from_uint(ptr) }
+ unsafe { SignalToken::cast_from_uint(ptr) }
}
// Decrements the count on the channel for a sleeper, returning the sleeper
pub use self::Failure::*;
use self::Blocker::*;
-use alloc::boxed::Box;
use vec::Vec;
use core::mem;
-use core::cell::UnsafeCell;
use sync::{atomic, Mutex, MutexGuard};
use comm::blocking::{mod, WaitToken, SignalToken};
/// Atomically blocks the current thread, placing it into `slot`, unlocking `lock`
/// in the meantime. This re-locks the mutex upon returning.
-fn wait<'a, 'b, T>(lock: &'a Mutex<State<T>>,
- guard: MutexGuard<'b, State<T>>,
- f: fn(BlockedTask) -> Blocker)
- -> MutexGuard<'a, State<T>>
+fn wait<'a, 'b, T: Send>(lock: &'a Mutex<State<T>>,
+ mut guard: MutexGuard<'b, State<T>>,
+ f: fn(SignalToken) -> Blocker)
+ -> MutexGuard<'a, State<T>>
{
let me: Box<Task> = Local::take();
me.deschedule(1, |task| {
}
pub fn send(&self, t: T) -> Result<(), T> {
- let guard = self.acquire_send_slot();
+ let mut guard = self.acquire_send_slot();
if guard.disconnected { return Err(t) }
guard.buf.enqueue(t);
let mut canceled = false;
assert!(guard.canceled.is_none());
guard.canceled = Some(unsafe { mem::transmute(&mut canceled) });
- let guard = wait(&self.lock, guard, BlockedSender);
+ let mut guard = wait(&self.lock, guard, BlockedSender);
if canceled {Err(guard.buf.dequeue())} else {Ok(())}
}
}
pub fn try_send(&self, t: T) -> Result<(), super::TrySendError<T>> {
- let guard = self.lock.lock();
+ let mut guard = self.lock.lock();
if guard.disconnected {
Err(super::RecvDisconnected(t))
} else if guard.buf.size() == guard.buf.cap() {
// When reading this, remember that there can only ever be one receiver at
// time.
pub fn recv(&self) -> Result<T, ()> {
- let guard = self.lock.lock();
+ let mut guard = self.lock.lock();
// Wait for the buffer to have something in it. No need for a while loop
// because we're the only receiver.
let mut waited = false;
if !guard.disconnected && guard.buf.size() == 0 {
- wait(&mut guard.blocker, BlockedReceiver, &self.lock);
+ guard = wait(&self.lock, guard, BlockedReceiver);
waited = true;
}
if guard.disconnected && guard.buf.size() == 0 { return Err(()) }
// Pick up the data, wake up our neighbors, and carry on
assert!(guard.buf.size() > 0);
let ret = guard.buf.dequeue();
- self.wakeup_senders(waited, guard, state);
+ self.wakeup_senders(waited, guard);
return Ok(ret);
}
pub fn try_recv(&self) -> Result<T, Failure> {
- let guard = self.lock();
+ let mut guard = self.lock.lock();
// Easy cases first
if guard.disconnected { return Err(Disconnected) }
// Be sure to wake up neighbors
let ret = Ok(guard.buf.dequeue());
- self.wakeup_senders(false, guard, state);
+ self.wakeup_senders(false, guard);
return ret;
}
// * `waited` - flag if the receiver blocked to receive some data, or if it
// just picked up some data on the way out
// * `guard` - the lock guard that is held over this channel's lock
- fn wakeup_senders(&self, waited: bool, guard: MutexGuard<State<T>>) {
+ fn wakeup_senders(&self, waited: bool, mut guard: MutexGuard<State<T>>) {
let pending_sender1: Option<SignalToken> = guard.queue.dequeue();
// If this is a no-buffer channel (cap == 0), then if we didn't wait we
}
// Not much to do other than wake up a receiver if one's there
- let guard = self.lock();
+ let mut guard = self.lock.lock();
if guard.disconnected { return }
guard.disconnected = true;
match mem::replace(&mut guard.blocker, NoneBlocked) {
}
pub fn drop_port(&self) {
- let guard = self.lock();
+ let mut guard = self.lock.lock();
if guard.disconnected { return }
guard.disconnected = true;
// If Ok, the value is whether this port has data, if Err, then the upgraded
// port needs to be checked instead of this one.
pub fn can_recv(&self) -> bool {
- let guard = self.lock();
+ let guard = self.lock.lock();
guard.disconnected || guard.buf.size() > 0
}
// Attempts to start selection on this port. This can either succeed or fail
// because there is data waiting.
pub fn start_selection(&self, token: SignalToken) -> StartResult {
- let guard = self.lock();
+ let mut guard = self.lock.lock();
if guard.disconnected || guard.buf.size() > 0 {
Abort
} else {
//
// The return value indicates whether there's data on this port.
pub fn abort_selection(&self) -> bool {
- let guard = self.lock();
+ let mut guard = self.lock.lock();
match mem::replace(&mut guard.blocker, NoneBlocked) {
NoneBlocked => true,
BlockedSender(token) => {
impl<T: Send> Drop for Packet<T> {
fn drop(&mut self) {
assert_eq!(self.channels.load(atomic::SeqCst), 0);
- let guard = self.lock();
+ let mut guard = self.lock.lock();
assert!(guard.queue.dequeue().is_none());
assert!(guard.canceled.is_none());
}
use result::Result::Ok;
use rt::backtrace;
use rt::util::{Stderr, Stdio};
-use rt::local::Local;
-use rt::task::Task;
use str::Str;
use string::String;
+use thread::Thread;
+use sys_common::thread_info;
// Defined in this module instead of io::stdio so that the unwinding
thread_local! {
}
};
let mut err = Stderr;
-
- // It is assumed that all reasonable rust code will have a local task at
- // all times. This means that this `exists` will return true almost all of
- // the time. There are border cases, however, when the runtime has
- // *almost* set up the local task, but hasn't quite gotten there yet. In
- // order to get some better diagnostics, we print on panic and
- // immediately abort the whole process if there is no local task
- // available.
- if !Local::exists(None::<Task>) {
- let _ = writeln!(&mut err, "panicked at '{}', {}:{}", msg, file, line);
- if backtrace::log_enabled() {
- let _ = backtrace::write(&mut err);
- } else {
- let _ = writeln!(&mut err, "run with `RUST_BACKTRACE=1` to \
- see a backtrace");
- }
- return
- }
-
- // Peel the name out of local task so we can print it. We've got to be sure
- // that the local task is in TLS while we're printing as I/O may occur.
- let (name, unwinding) = {
- let mut t = Local::borrow(None::<Task>);
- (t.name.take(), t.unwinder.unwinding())
- };
- {
- let n = name.as_ref().map(|n| n.as_slice()).unwrap_or("<unnamed>");
-
- let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
- match prev {
- Some(mut stderr) => {
- // FIXME: what to do when the task printing panics?
- let _ = writeln!(stderr,
- "task '{}' panicked at '{}', {}:{}\n",
- n, msg, file, line);
- if backtrace::log_enabled() {
- let _ = backtrace::write(&mut *stderr);
- }
- let mut s = Some(stderr);
- LOCAL_STDERR.with(|slot| {
- *slot.borrow_mut() = s.take();
- });
+ let thread = Thread::current();
+ let name = thread.name().unwrap_or("<unnamed>");
+ let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
+ match prev {
+ Some(mut stderr) => {
+ // FIXME: what to do when the thread printing panics?
+ let _ = writeln!(stderr,
+ "thread '{}' panicked at '{}', {}:{}\n",
+ name, msg, file, line);
+ if backtrace::log_enabled() {
+ let _ = backtrace::write(&mut *stderr);
}
- None => {
- let _ = writeln!(&mut err, "task '{}' panicked at '{}', {}:{}",
- n, msg, file, line);
- if backtrace::log_enabled() {
- let _ = backtrace::write(&mut err);
- }
+ let mut s = Some(stderr);
+ LOCAL_STDERR.with(|slot| {
+ *slot.borrow_mut() = s.take();
+ });
+ }
+ None => {
+ let _ = writeln!(&mut err, "thread '{}' panicked at '{}', {}:{}",
+ name, msg, file, line);
+ if backtrace::log_enabled() {
+ let _ = backtrace::write(&mut err);
}
}
+ }
- // If this is a double panic, make sure that we printed a backtrace
- // for this panic.
- if unwinding && !backtrace::log_enabled() {
- let _ = backtrace::write(&mut err);
- }
+ // If this is a double panic, make sure that we printed a backtrace
+ // for this panic.
+ if thread_info::panicking() && !backtrace::log_enabled() {
+ let _ = backtrace::write(&mut err);
}
- Local::borrow(None::<Task>).name = name;
}
use prelude::*;
use super::*;
use io;
- use task;
+ use thread::Thread;
#[test]
fn test_rx_reader() {
let (tx, rx) = channel();
- task::spawn(move|| {
+ Thread::spawn(move|| {
tx.send(vec![1u8, 2u8]);
tx.send(vec![]);
tx.send(vec![3u8, 4u8]);
#[test]
fn test_rx_buffer() {
let (tx, rx) = channel();
- task::spawn(move|| {
+ Thread::spawn(move|| {
tx.send(b"he".to_vec());
tx.send(b"llo wo".to_vec());
tx.send(b"".to_vec());
writer.write_be_u32(42).unwrap();
let wanted = vec![0u8, 0u8, 0u8, 42u8];
+<<<<<<< HEAD
let got = match task::try(move|| { rx.recv() }) {
+=======
+ let got = match Thread::with_join(proc() { rx.recv() }).join() {
+>>>>>>> Fallout from new thread API
Ok(got) => got,
Err(_) => panic!(),
};
Err(ref e) if e.kind == TimedOut => {}
Err(e) => panic!("error: {}", e),
}
- ::task::deschedule();
+ ::thread::Thread::yield_now();
if i == 1000 { panic!("should have a pending connection") }
}
drop(l);
Err(ref e) if e.kind == TimedOut => {}
Err(e) => panic!("error: {}", e),
}
- ::task::deschedule();
+ ::thread::Thread::yield_now();
if i == 1000 { panic!("should have a pending connection") }
}
}
// Try to ensure that the reading clone is indeed reading
for _ in range(0i, 50) {
- ::task::deschedule();
+ ::thread::Thread::yield_now();
}
// clone the handle again while it's reading, then let it finish the
use std::hash::sip::SipState;
use io::pipe::{PipeStream, PipePair};
use path::BytesContainer;
+use thread::Thread;
use sys;
use sys::fs::FileDesc;
fn read(stream: Option<io::PipeStream>) -> Receiver<IoResult<Vec<u8>>> {
let (tx, rx) = channel();
match stream {
- Some(stream) => spawn(move |:| {
- let mut stream = stream;
- tx.send(stream.read_to_end())
- }),
+ Some(stream) => {
+ Thread::spawn(move |:| {
+ let mut stream = stream;
+ tx.send(stream.read_to_end())
+ });
+ }
None => tx.send(Ok(Vec::new()))
}
rx
use option::Option::{Some, None};
use ops::{Deref, DerefMut, FnOnce};
use result::Result::{Ok, Err};
-use rt;
-use rt::local::Local;
-use rt::task::Task;
use slice::SliceExt;
use str::StrPrelude;
use string::String;
// // io1 aliases io2
// })
// })
-fn with_task_stdout<F>(f: F) where
- F: FnOnce(&mut Writer) -> IoResult<()>,
-{
- let result = if Local::exists(None::<Task>) {
- let mut my_stdout = LOCAL_STDOUT.with(|slot| {
- slot.borrow_mut().take()
- }).unwrap_or_else(|| {
- box stdout() as Box<Writer + Send>
- });
- let result = f(&mut *my_stdout);
- let mut var = Some(my_stdout);
- LOCAL_STDOUT.with(|slot| {
- *slot.borrow_mut() = var.take();
- });
- result
- } else {
- let mut io = rt::util::Stdout;
- f(&mut io as &mut Writer)
- };
+fn with_task_stdout(f: |&mut Writer| -> IoResult<()>) {
+ let mut my_stdout = LOCAL_STDOUT.with(|slot| {
+ slot.borrow_mut().take()
+ }).unwrap_or_else(|| {
+ box stdout() as Box<Writer + Send>
+ });
+ let result = f(&mut *my_stdout);
+ let mut var = Some(my_stdout);
+ LOCAL_STDOUT.with(|slot| {
+ *slot.borrow_mut() = var.take();
+ });
match result {
Ok(()) => {}
Err(e) => panic!("failed printing to stdout: {}", e),
/* Threads and communication */
+pub mod task;
+#[allow(missing_docs)]
pub mod thread;
pub mod sync;
pub mod comm;
use ptr;
use result::Result;
use result::Result::{Err, Ok};
-use slice::{AsSlice, SliceExt, PartialEqSliceExt};
+use slice::{AsSlice, SliceExt};
use slice::CloneSliceExt;
use str::{Str, StrPrelude, StrAllocating};
use string::{String, ToString};
#[test]
fn test_null_byte() {
- use task;
- let result = task::try(move|| {
+ use thread::Thread;
+ let result = Thread::with_join(move|| {
Path::new(b"foo/bar\0")
- });
+ }).join();
assert!(result.is_err());
- let result = task::try(move|| {
+ let result = Thread::with_join(move|| {
Path::new("test").set_filename(b"f\0o")
- });
+ }).join();
assert!(result.is_err());
- let result = task::try(move|| {
+ let result = Thread::with_join(move|| {
Path::new("test").push(b"f\0o");
- });
+ }).join();
assert!(result.is_err());
}
#[test]
fn test_null_byte() {
- use task;
- let result = task::try(move|| {
+ use thread::Thread;
+ let result = Thread::with_join(move|| {
Path::new(b"foo/bar\0")
- });
+ }).join();
assert!(result.is_err());
- let result = task::try(move|| {
+ let result = Thread::with_join(move|| {
Path::new("test").set_filename(b"f\0o")
- });
+ }).join();
assert!(result.is_err());
- let result = task::try(move|| {
+ let result = Thread::with_join(move|| {
Path::new("test").push(b"f\0o");
- });
+ }).join();
assert!(result.is_err());
}
use super::OsRng;
use rand::Rng;
- use task;
+ use thread::Thread;
#[test]
fn test_os_rng() {
for _ in range(0u, 20) {
let (tx, rx) = channel();
txs.push(tx);
- task::spawn(move|| {
+
+ Thread::spawn(move|| {
// wait until all the tasks are ready to go.
rx.recv();
// deschedule to attempt to interleave things as much
// as possible (XXX: is this a good test?)
let mut r = OsRng::new().unwrap();
- task::deschedule();
+ Thread::yield_now();
let mut v = [0u8, .. 1000];
for _ in range(0u, 100) {
r.next_u32();
- task::deschedule();
+ Thread::yield_now();
r.next_u64();
- task::deschedule();
+ Thread::yield_now();
r.fill_bytes(&mut v);
- task::deschedule();
+ Thread::yield_now();
}
- })
+ });
}
// start all the tasks
use core::prelude::*;
-use libc;
use boxed::Box;
use vec::Vec;
use sync::{Mutex, atomic, Once, ONCE_INIT};
static INIT: Once = ONCE_INIT;
static QUEUE: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT;
-static RUNNING: atomic::AtomicBool = atomic::INIT_ATOMIC_BOOL;
fn init() {
let state: Box<Queue> = box Mutex::new(Vec::new());
unsafe {
QUEUE.store(mem::transmute(state), atomic::SeqCst);
- libc::atexit(run);
+
+ // FIXME: switch this to use atexit as below. Currently this
+ // segfaults (the queue's memory is mysteriously gone), so
+ // instead the cleanup is tied to the `std::rt` entry point.
+ //
+ // ::libc::atexit(cleanup);
}
}
-// Note: this is private and so can only be called via atexit above,
-// which guarantees initialization.
-extern fn run() {
- let cur = unsafe {
- rtassert!(!RUNNING.load(atomic::SeqCst));
+pub fn cleanup() {
+ unsafe {
let queue = QUEUE.swap(0, atomic::SeqCst);
- rtassert!(queue != 0);
-
- let queue: Box<Queue> = mem::transmute(queue);
- let v = mem::replace(&mut *queue.lock(), Vec::new());
- v
- };
-
- for to_run in cur.into_iter() {
- to_run.invoke(());
+ if queue != 0 {
+ let queue: Box<Queue> = mem::transmute(queue);
+ let v = mem::replace(&mut *queue.lock(), Vec::new());
+ for to_run in v.into_iter() {
+ to_run.invoke();
+ }
+ }
}
}
// all with respect to `run`, meaning that this could theoretically be a
// use-after-free. There's not much we can do to protect against that,
// however. Let's just assume a well-behaved runtime and go from there!
- rtassert!(!RUNNING.load(atomic::SeqCst));
let queue = QUEUE.load(atomic::SeqCst);
rtassert!(queue != 0);
(*(queue as *const Queue)).lock().push(f);
#![allow(non_camel_case_types)]
-use io::{IoResult, Writer};
-use iter::{Iterator, IteratorExt};
use option::Option::{Some, None};
use os;
-use result::Result::{Ok, Err};
-use str::{StrPrelude, from_str};
use sync::atomic;
pub use sys::backtrace::write;
#![allow(dead_code)]
-use borrow::IntoCow;
use failure;
use os;
use thunk::Thunk;
use kinds::Send;
use thread::Thread;
+use sys;
use sys_common;
-use sys_common::thread::{mod, NewThread};
+use sys_common::thread_info::{mod, NewThread};
// Reexport some of our utilities which are expected by other crates.
pub use self::util::{default_sched_threads, min_stack, running_on_valgrind};
/// Initializes global state, including frobbing
/// the crate's logging flags, registering GC
/// metadata, and storing the process arguments.
+// FIXME: this should be unsafe
#[allow(experimental)]
pub fn init(argc: int, argv: *const *const u8) {
- // FIXME: Derefing these pointers is not safe.
- // Need to propagate the unsafety to `start`.
unsafe {
args::init(argc, argv);
thread::init();
pub fn start(argc: int, argv: *const *const u8, main: Thunk) -> int {
use prelude::*;
use rt;
- use rt::task::Task;
- use str;
let something_around_the_top_of_the_stack = 1;
let addr = &something_around_the_top_of_the_stack as *const int;
init(argc, argv);
let mut exit_code = None;
- let thread: std::Thread = NewThread::new(Some("<main>".into_string()));
+ let thread: Thread = NewThread::new(Some("<main>".into_string()));
thread_info::set((my_stack_bottom, my_stack_top),
unsafe { sys::thread::guard::main() },
thread);
- unwind::try(|| {
- unsafe {
+ let mut main_opt = Some(main); // option dance
+ unsafe {
+ let _ = unwind::try(|| {
sys_common::stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top);
- }
- (main.take().unwrap()).invoke(());
- exit_code = Some(os::get_exit_status());
- });
- unsafe { cleanup(); }
+ (main_opt.take().unwrap()).invoke();
+ exit_code = Some(os::get_exit_status());
+ });
+ cleanup();
+ }
// If the exit code wasn't set, then the task block must have panicked.
return exit_code.unwrap_or(rt::DEFAULT_ERROR_CODE);
}
/// undefined behavior.
pub unsafe fn cleanup() {
args::cleanup();
- thread::cleanup();
-}
-
-// FIXME: these probably shouldn't be public...
-#[doc(hidden)]
-pub mod shouldnt_be_public {
- #[cfg(not(test))]
- pub use super::local_ptr::native::maybe_tls_key;
- #[cfg(all(not(windows), not(target_os = "android"), not(target_os = "ios")))]
- pub use super::local_ptr::compiled::RT_TLS_PTR;
+ sys::stack_overflow::cleanup();
+ at_exit_imp::cleanup();
}
// Now that we've run all the necessary unwind callbacks, we actually
// perform the unwinding.
- if thread_info::unwinding() {
+ if thread_info::panicking() {
// If a thread panics while it's already unwinding then we
// have limited options. Currently our preference is to
// just abort. In the future we may consider resuming
}
pub unsafe fn report_overflow() {
- use rt::task::Task;
- use rt::local::Local;
+ use thread::Thread;
// See the message below for why this is not emitted to the
// ^ Where did the message below go?
// call would happen to initialized it (calling out to libuv),
// and the FFI call needs 2MB of stack when we just ran out.
- let task: Option<*mut Task> = Local::try_unsafe_borrow();
-
- let name = task.and_then(|task| {
- (*task).name.as_ref().map(|n| n.as_slice())
- });
-
- rterrln!("\ntask '{}' has overflowed its stack", name.unwrap_or("<unknown>"));
+ rterrln!("\nthread '{}' has overflowed its stack",
+ Thread::current().name().unwrap_or("<unknown>"));
}
use self::FutureState::*;
use comm::{Receiver, channel};
-use task::spawn;
use thunk::{Thunk};
+use thread::Thread;
/// A type encapsulating the result of a computation which may not be complete
pub struct Future<A> {
let (tx, rx) = channel();
- spawn(move |:| {
+ Thread::spawn(move |:| {
// Don't panic if the other end has hung up
let _ = tx.send_opt(blk());
});
mod test {
use prelude::*;
- use task;
+ use thread::Thread;
use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar};
#[test]
fn test_mutex_arc_poison() {
let arc = Arc::new(Mutex::new(1i));
let arc2 = arc.clone();
- let _ = task::try(move|| {
+ let _ = Thread::with_join(move|| {
let lock = arc2.lock();
assert_eq!(*lock, 2);
- });
+ }).join();
let lock = arc.lock();
assert_eq!(*lock, 1);
}
fn test_mutex_arc_access_in_unwind() {
let arc = Arc::new(Mutex::new(1i));
let arc2 = arc.clone();
- let _ = task::try(move|| -> () {
+ let _ = Thread::with_join::<()>(move|| -> () {
struct Unwinder {
i: Arc<Mutex<int>>,
}
}
let _u = Unwinder { i: arc2 };
panic!();
- });
+ }).join();
let lock = arc.lock();
assert_eq!(*lock, 2);
}
mod test {
use prelude::*;
- use task;
+ use thread::Thread;
use super::{ONCE_INIT, Once};
#[test]
for _ in range(0u, 10) {
let tx = tx.clone();
spawn(move|| {
- for _ in range(0u, 4) { task::deschedule() }
+ for _ in range(0u, 4) { Thread::yield_now() }
unsafe {
O.doit(|| {
assert!(!run);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use option::Option::None;
-use rustrt::task::Task;
-use rustrt::local::Local;
+use thread::Thread;
pub struct Flag { pub failed: bool }
impl Flag {
pub fn borrow(&mut self) -> Guard {
- Guard { flag: &mut self.failed, failing: failing() }
+ Guard { flag: &mut self.failed, panicking: Thread::panicking() }
}
}
pub struct Guard<'a> {
flag: &'a mut bool,
- failing: bool,
+ panicking: bool,
}
impl<'a> Guard<'a> {
}
pub fn done(&mut self) {
- if !self.failing && failing() {
+ if !self.panicking && Thread::panicking() {
*self.flag = true;
}
}
}
-
-fn failing() -> bool {
- if Local::exists(None::<Task>) {
- Local::borrow(None::<Task>).unwinder.unwinding()
- } else {
- false
- }
-}
use prelude::*;
use rand::{mod, Rng};
- use task;
+ use thread::Thread;
use sync::{Arc, RWLock, StaticRWLock, RWLOCK_INIT};
#[test]
fn test_rw_arc_poison_wr() {
let arc = Arc::new(RWLock::new(1i));
let arc2 = arc.clone();
- let _ = task::try(move|| {
+ let _ = Thread::with_join(move|| {
let lock = arc2.write();
assert_eq!(*lock, 2);
- });
+ }).join();
let lock = arc.read();
assert_eq!(*lock, 1);
}
fn test_rw_arc_poison_ww() {
let arc = Arc::new(RWLock::new(1i));
let arc2 = arc.clone();
- let _ = task::try(move|| {
+ let _ = Thread::with_join(move|| {
let lock = arc2.write();
assert_eq!(*lock, 2);
- });
+ }).join();
let lock = arc.write();
assert_eq!(*lock, 1);
}
fn test_rw_arc_no_poison_rr() {
let arc = Arc::new(RWLock::new(1i));
let arc2 = arc.clone();
- let _ = task::try(move|| {
+ let _ = Thread::with_join(move|| {
let lock = arc2.read();
assert_eq!(*lock, 2);
- });
+ }).join();
let lock = arc.read();
assert_eq!(*lock, 1);
}
fn test_rw_arc_no_poison_rw() {
let arc = Arc::new(RWLock::new(1i));
let arc2 = arc.clone();
- let _ = task::try(move|| {
+ let _ = Thread::with_join(move|| {
let lock = arc2.read();
assert_eq!(*lock, 2);
- });
+ }).join();
let lock = arc.write();
assert_eq!(*lock, 1);
}
let arc2 = arc.clone();
let (tx, rx) = channel();
- task::spawn(move|| {
+ Thread::spawn(move|| {
let mut lock = arc2.write();
for _ in range(0u, 10) {
let tmp = *lock;
*lock = -1;
- task::deschedule();
+ Thread::yield_now();
*lock = tmp + 1;
}
tx.send(());
let mut children = Vec::new();
for _ in range(0u, 5) {
let arc3 = arc.clone();
- children.push(task::try_future(move|| {
+ children.push(Thread::with_join(move|| {
let lock = arc3.read();
assert!(*lock >= 0);
}));
}
// Wait for children to pass their asserts
- for r in children.iter_mut() {
- assert!(r.get_ref().is_ok());
+ for r in children.into_iter() {
+ assert!(r.join().is_ok());
}
// Wait for writer to finish
fn test_rw_arc_access_in_unwind() {
let arc = Arc::new(RWLock::new(1i));
let arc2 = arc.clone();
+<<<<<<< HEAD
let _ = task::try(move|| -> () {
+=======
+ let _ = Thread::with_join::<()>(proc() {
+>>>>>>> Fallout from new thread API
struct Unwinder {
i: Arc<RWLock<int>>,
}
}
let _u = Unwinder { i: arc2 };
panic!();
- });
+ }).join();
let lock = arc.read();
assert_eq!(*lock, 2);
}
use core::prelude::*;
-use task::{spawn};
+use thread::Thread;
use comm::{channel, Sender, Receiver};
use sync::{Arc, Mutex};
use thunk::Thunk;
}
fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) {
- spawn(move |:| {
+ Thread::spawn(move |:| {
// Will spawn a new task on panic unless it is cancelled.
let sentinel = Sentinel::new(&jobs);
}
sentinel.cancel();
- })
+ });
}
#[cfg(test)]
waiter.wait();
}
}
-
// except according to those terms.
use io::{IoResult, Writer};
-use iter::Iterator;
+use iter::{Iterator, IteratorExt};
use option::{Some, None};
use result::{Ok, Err};
use str::{StrPrelude, from_str};
use rt;
use sys::helper_signal;
-use task;
+use thread::Thread;
/// A structure for management of a helper thread.
///
*self.signal.get() = send as uint;
let t = f();
+<<<<<<< HEAD
task::spawn(move |:| {
+=======
+ Thread::spawn(proc() {
+>>>>>>> Fallout from new thread API
helper(receive, rx, t);
let _g = self.lock.lock();
*self.shutdown.get() = true;
pub mod rwlock;
pub mod stack;
pub mod thread;
+pub mod thread_info;
pub mod thread_local;
// common error constructors
*c.borrow_mut() = Some(ThreadInfo {
stack_bounds: (0, 0),
stack_guard: 0,
- unwinder: false,
- thread: Thread::new(None),
+ unwinding: false,
+ thread: NewThread::new(None),
})
}
- f(c.borrow_mut().as_ref().unwrap())
+ f(c.borrow_mut().as_mut().unwrap())
})
}
}
}
pub fn panicking() -> bool {
- ThreadInfo::with(|info| info.unwinder.unwinding())
+ ThreadInfo::with(|info| info.unwinding)
}
pub fn stack_guard() -> uint {
ThreadInfo::with(|info| info.stack_guard)
}
-pub fn unwinding() -> bool {
- ThreadInfo::with(|info| info.unwinder.unwinding)
-}
-
pub fn set_unwinding(unwinding: bool) {
ThreadInfo::with(|info| info.unwinding = unwinding)
}
pub fn set(stack_bounds: (uint, uint), stack_guard: uint, thread: Thread) {
THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
+ let mut thread_opt = Some(thread); // option dance
THREAD_INFO.with(|c| *c.borrow_mut() = Some(ThreadInfo{
stack_bounds: stack_bounds,
stack_guard: stack_guard,
unwinding: false,
- thread: thread,
+ thread: thread_opt.take().unwrap(),
}));
}
use prelude::*;
-use rt;
use sync::atomic::{mod, AtomicUint};
use sync::{Mutex, Once, ONCE_INIT};
struct Context<'a> {
idx: int,
- writer: &'a mut Writer+'a,
+ writer: &'a mut (Writer+'a),
last_error: Option<IoError>,
}
use self::signal::{siginfo, sigaction, SIGBUS, SIG_DFL,
SA_SIGINFO, SA_ONSTACK, sigaltstack,
SIGSTKSZ};
- use rt::local::Local;
- use rt::task::Task;
use libc;
use libc::funcs::posix88::mman::{mmap, munmap};
use libc::consts::os::posix88::{SIGSEGV,
MAP_ANON,
MAP_FAILED};
+ use sys_common::thread_info;
+
// This is initialized in init() and only read from after
static mut PAGE_SIZE: uint = 0;
- // get_task_info is called from an exception / signal handler.
- // It returns the guard page of the current task or 0 if that
- // guard page doesn't exist. None is returned if there's currently
- // no local task.
- unsafe fn get_task_guard_page() -> Option<uint> {
- let task: Option<*mut Task> = Local::try_unsafe_borrow();
- task.map(|task| (&*task).stack_guard().unwrap_or(0))
- }
-
-
#[no_stack_check]
unsafe extern fn signal_handler(signum: libc::c_int,
info: *mut siginfo,
// We're calling into functions with stack checks
stack::record_sp_limit(0);
- match get_task_guard_page() {
- Some(guard) => {
- let addr = (*info).si_addr as uint;
+ let guard = thread_info::stack_guard();
+ let addr = (*info).si_addr as uint;
- if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard {
- term(signum);
- }
+ if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard {
+ term(signum);
+ }
- report_overflow();
+ report_overflow();
- intrinsics::abort()
- }
- None => term(signum)
- }
+ intrinsics::abort()
}
static mut MAIN_ALTSTACK: *mut libc::c_void = 0 as *mut libc::c_void;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use rt::local::Local;
-use rt::task::Task;
use rt::util::report_overflow;
use core::prelude::*;
use ptr;
use mem;
use libc;
use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL};
-use sys_common::stack;
+use sys_common::{stack, thread_info};
pub struct Handler {
_data: *mut libc::c_void
// guard page doesn't exist. None is returned if there's currently
// no local task.
unsafe fn get_task_guard_page() -> Option<uint> {
- let task: Option<*mut Task> = Local::try_unsafe_borrow();
- task.map(|task| (&*task).stack_guard().unwrap_or(0))
+ thread_info::stack_guard()
}
// This is initialized in init() and only read from after
#![deprecated = "use std::thread instead"]
+use any::Any;
+use boxed::Box;
use thread;
use kinds::Send;
+use result::Result;
/// Deprecate: use `std::thread::Cfg` instead.
#[deprecated = "use std::thread::Cfg instead"]
pub fn spawn(f: proc(): Send) {
thread::Thread::spawn(f);
}
+
+/// Deprecated: use `std::thread::Thread::with_join instead`.
+#[deprecated = "use std::thread::Thread::with_join instead"]
+pub fn try<T: Send>(f: proc(): Send -> T) -> Result<T, Box<Any + Send>> {
+ thread::Thread::with_join(f).join()
+}
+
+/// Deprecated: use `std::thread::Thread::yield_now instead`.
+#[deprecated = "use std::thread::Thread::yield_now instead"]
+pub fn deschedule() {
+ thread::Thread::yield_now()
+}
}
thread_info::set(
(my_stack_bottom, my_stack_top),
- thread::current_guard_page(),
+ unsafe { imp::guard::current() },
their_thread
);
}
}
};
- (unsafe { imp::create(stack, box main) }, my_thread)
+ (unsafe { imp::create(stack_size, box main) }, my_thread)
}
/// Spawn a detached thread, and return a handle to it.
// We need the address of the packet to fill in to be stable so when
// `main` fills it in it's still valid, so allocate an extra box to do
// so.
- let my_packet = box Err(box 0); // sentinel value
+ let any: Box<Any+Send> = box 0u8; // sentinel value
+ let my_packet = box Err(any);
let their_packet: *mut Result<T> = unsafe {
*mem::transmute::<&Box<Result<T>>, *const *mut Result<T>>(&my_packet)
};
let (native, thread) = self.core_spawn(f, proc(result) {
- *their_packet = result;
+ unsafe { *their_packet = result; }
});
JoinGuard {
native: native,
joined: false,
- packet: my_packet,
+ packet: Some(my_packet),
thread: thread,
}
}
/// Gets a handle to the thread that invokes it.
pub fn current() -> Thread {
- ThreadInfo::current_thread()
+ thread_info::current_thread()
}
/// Cooperatively give up a timeslice to the OS scheduler.
/// Determines whether the current thread is panicking.
pub fn panicking() -> bool {
- ThreadInfo::panicking()
+ thread_info::panicking()
}
// http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp
/// See the module doc for more detail.
pub fn park() {
let thread = Thread::current();
- let guard = thread.inner.lock.lock();
+ let mut guard = thread.inner.lock.lock();
while !*guard {
- thread.inner.cvar.wait(guard);
+ thread.inner.cvar.wait(&guard);
}
*guard = false;
}
///
/// See the module doc for more detail.
pub fn unpark(&self) {
- let guard = self.inner.lock();
+ let mut guard = self.inner.lock.lock();
if !*guard {
*guard = true;
self.inner.cvar.notify_one();
/// Get the thread's name.
pub fn name(&self) -> Option<&str> {
- self.inner.name.as_ref()
+ self.inner.name.as_ref().map(|s| s.as_slice())
}
}
/// Indicates the manner in which a thread exited.
///
/// A thread that completes without panicking is considered to exit successfully.
-pub type Result<T> = result::Result<T, Box<Any + Send>>;
+pub type Result<T> = ::result::Result<T, Box<Any + Send>>;
#[must_use]
/// An RAII guard that will block until thread termination when dropped.
native: imp::rust_thread,
thread: Thread,
joined: bool,
- packet: Box<Result<T>>,
+ packet: Option<Box<Result<T>>>,
}
impl<T: Send> JoinGuard<T> {
use prelude::*;
use cell::UnsafeCell;
- use rt::thread::Thread;
+ use thread::Thread;
struct Foo(Sender<()>);
}
}
- Thread::start(move|| {
+ Thread::with_join(move|| {
drop(S1);
}).join();
}
}
}
- Thread::start(move|| unsafe {
+ Thread::with_join(move|| unsafe {
K1.with(|s| *s.get() = Some(S1));
}).join();
}
use std::os;
use std::str::FromStr;
use std::string::String;
-use std::task::TaskBuilder;
+use std::thread::{mod, Thread};
use std::time::Duration;
use std::thunk::{Thunk, Invoke};
monitor_ch: Sender<MonitorMsg>,
nocapture: bool,
testfn: Thunk) {
- spawn(move || {
+ Thread::spawn(move || {
let (tx, rx) = channel();
let mut reader = ChanReader::new(rx);
let stdout = ChanWriter::new(tx.clone());
let stderr = ChanWriter::new(tx);
- let mut task = TaskBuilder::new().named(match desc.name {
+ let mut cfg = thread::cfg().name(match desc.name {
DynTestName(ref name) => name.clone().to_string(),
StaticTestName(name) => name.to_string(),
});
if nocapture {
drop((stdout, stderr));
} else {
- task = task.stdout(box stdout as Box<Writer + Send>);
- task = task.stderr(box stderr as Box<Writer + Send>);
+ cfg = cfg.stdout(box stdout as Box<Writer + Send>);
+ cfg = cfg.stderr(box stderr as Box<Writer + Send>);
}
- let result_future = task.try_future(move || testfn.invoke(()));
+ let result_guard = cfg.with_join(testfn);
let stdout = reader.read_to_end().unwrap().into_iter().collect();
- let task_result = result_future.into_inner();
- let test_result = calc_result(&desc, task_result);
+ let test_result = calc_result(&desc, result_guard.join());
monitor_ch.send((desc.clone(), test_result, stdout));
- })
+ });
}
match testfn {
// It's unclear how likely such a bug is to recur, but it seems like a
// scenario worth testing.
-use std::task;
+use std::thread::Thread;
enum Conzabble {
Bickwick(Foo)
}
pub fn main() {
- task::try(fails);
+ Thread::with_join(fails).join();
}
// except according to those terms.
use std::io::{ChanReader, ChanWriter};
-use std::task::TaskBuilder;
+use std::thread;
fn main() {
let (tx, rx) = channel();
let mut reader = ChanReader::new(rx);
let stderr = ChanWriter::new(tx);
- let res = TaskBuilder::new().stderr(box stderr as Box<Writer + Send>).try(move|| -> () {
+ let res = thread::cfg().stderr(box stderr as Box<Writer + Send>).with_join(move|| -> () {
panic!("Hello, world!")
- });
+ }).join();
assert!(res.is_err());
let output = reader.read_to_string().unwrap();